Konvertieren Sie UTF-8 mit BOM in UTF-8 ohne BOM in Python

Lesezeit: 5 Minuten

Konvertieren Sie UTF 8 mit BOM in UTF 8 ohne BOM in
Pauke

Zwei Fragen hier. Ich habe eine Reihe von Dateien, die normalerweise UTF-8 mit BOM sind. Ich möchte sie (idealerweise vorhanden) ohne BOM in UTF-8 konvertieren. Wie es scheint codecs.StreamRecoder(stream, encode, decode, Reader, Writer, errors) würde damit umgehen. Aber ich sehe keine wirklich guten Beispiele für die Verwendung. Wäre dies der beste Weg, damit umzugehen?

source files:
Tue Jan 17$ file brh-m-157.json 
brh-m-157.json: UTF-8 Unicode (with BOM) text

Außerdem wäre es ideal, wenn wir ohne explizites Wissen mit unterschiedlichen Eingabecodierungen umgehen könnten (siehe ASCII und UTF-16). Das scheint alles machbar zu sein. Gibt es eine Lösung, die jede bekannte Python-Codierung verwenden und als UTF-8 ohne BOM ausgeben kann?

bearbeiten 1 vorgeschlagene Sol’n von unten (Danke!)

fp = open('brh-m-157.json','rw')
s = fp.read()
u = s.decode('utf-8-sig')
s = u.encode('utf-8')
print fp.encoding  
fp.write(s)

Dies gibt mir den folgenden Fehler:

IOError: [Errno 9] Bad file descriptor

Newsflash

In Kommentaren wird mir gesagt, dass der Fehler darin besteht, dass ich die Datei mit dem Modus „rw“ anstelle von „r+“https://stackoverflow.com/“r+b“ öffne, also sollte ich meine Frage eventuell erneut bearbeiten und entfernen der gelöste Teil.

  • Sie müssen Ihre Datei zum Lesen plus Update öffnen, dh mit a r+ Modus. Hinzufügen b auch so, dass es auch unter Windows ohne irgendwelche komischen Zeilenenden funktioniert. Schließlich sollten Sie zum Anfang der Datei zurückkehren und sie am Ende abschneiden – siehe meine aktualisierte Antwort.

    – Martin Geisler

    17. Januar 12 um 21:58 Uhr

Konvertieren Sie UTF 8 mit BOM in UTF 8 ohne BOM in
Martin Geißler

Nutzen Sie einfach die “utf-8-sig”-Codec:

fp = open("file.txt")
s = fp.read()
u = s.decode("utf-8-sig")

Das gibt dir ein unicode Zeichenfolge ohne die Stückliste. Sie können dann verwenden

s = u.encode("utf-8")

um eine normale UTF-8-codierte Zeichenfolge wieder einzufügen s. Wenn Ihre Dateien groß sind, sollten Sie vermeiden, sie alle in den Speicher zu lesen. Die Stückliste besteht einfach aus drei Bytes am Anfang der Datei, sodass Sie diesen Code verwenden können, um sie aus der Datei zu entfernen:

import os, sys, codecs

BUFSIZE = 4096
BOMLEN = len(codecs.BOM_UTF8)

path = sys.argv[1]
with open(path, "r+b") as fp:
    chunk = fp.read(BUFSIZE)
    if chunk.startswith(codecs.BOM_UTF8):
        i = 0
        chunk = chunk[BOMLEN:]
        while chunk:
            fp.seek(i)
            fp.write(chunk)
            i += len(chunk)
            fp.seek(BOMLEN, os.SEEK_CUR)
            chunk = fp.read(BUFSIZE)
        fp.seek(-BOMLEN, os.SEEK_CUR)
        fp.truncate()

Es öffnet die Datei, liest einen Teil und schreibt es 3 Bytes früher als dort, wo es es gelesen hat, in die Datei. Die Datei wird an Ort und Stelle neu geschrieben. Als einfachere Lösung besteht darin, die kürzere Datei wie die Antwort von newtover in eine neue Datei zu schreiben. Das wäre einfacher, verbraucht aber kurzzeitig den doppelten Speicherplatz.

Um die Codierung zu erraten, können Sie die Codierung einfach von den meisten bis zu den am wenigsten spezifischen durchlaufen:

def decode(s):
    for encoding in "utf-8-sig", "utf-16":
        try:
            return s.decode(encoding)
        except UnicodeDecodeError:
            continue
    return s.decode("latin-1") # will always work

Eine UTF-16-codierte Datei wird nicht als UTF-8 decodiert, also versuchen wir es zuerst mit UTF-8. Wenn das fehlschlägt, versuchen wir es mit UTF-16. Schließlich verwenden wir Latin-1 – das wird immer funktionieren, da alle 256 Bytes gültige Werte in Latin-1 sind. Vielleicht möchten Sie zurückkehren None Stattdessen in diesem Fall, da es sich wirklich um ein Fallback handelt und Ihr Code dies möglicherweise sorgfältiger handhaben möchte (wenn dies möglich ist).

  • hmm, ich habe die Frage in Bearbeitung Nr. 1 mit Beispielcode aktualisiert, aber einen schlechten Dateideskriptor erhalten. thx für jede hilfe. Ich versuche das herauszufinden.

    – Pauke

    17. Januar 12 um 17:29 Uhr

  • scheint bekommen AttributeError: 'str' object has no attribute 'decode'. Also habe ich endlich den Code als verwendet with open(filename,encoding='utf-8-sig') as f_content:dann doc = f_content.read() und es hat bei mir funktioniert.

    – Clemens116

    20. April 21 um 19:21 Uhr


1643559367 245 Konvertieren Sie UTF 8 mit BOM in UTF 8 ohne BOM in
Geng Jiawen

In Python 3 ist es ganz einfach: Datei lesen und neu schreiben mit utf-8 Codierung:

s = open(bom_file, mode="r", encoding='utf-8-sig').read()
open(bom_file, mode="w", encoding='utf-8').write(s)

import codecs
import shutil
import sys

s = sys.stdin.read(3)
if s != codecs.BOM_UTF8:
    sys.stdout.write(s)

shutil.copyfileobj(sys.stdin, sys.stdout)

  • Können Sie erklären, wie dieser Code funktioniert? $ remove_bom.py < input.txt > output.txt Habe ich recht?

    – guneysus

    2. November 13 um 12:38 Uhr

  • @guneysus, ja genau

    – neu

    2. November 13 um 18:55 Uhr

Dies ist meine Implementierung, um jede Art von Codierung ohne BOM in UTF-8 zu konvertieren und Windows-Enlines durch das universelle Format zu ersetzen:

def utf8_converter(file_path, universal_endline=True):
    '''
    Convert any type of file to UTF-8 without BOM
    and using universal endline by default.

    Parameters
    ----------
    file_path : string, file path.
    universal_endline : boolean (True),
                        by default convert endlines to universal format.
    '''

    # Fix file path
    file_path = os.path.realpath(os.path.expanduser(file_path))

    # Read from file
    file_open = open(file_path)
    raw = file_open.read()
    file_open.close()

    # Decode
    raw = raw.decode(chardet.detect(raw)['encoding'])
    # Remove windows end line
    if universal_endline:
        raw = raw.replace('rn', 'n')
    # Encode to UTF-8
    raw = raw.encode('utf8')
    # Remove BOM
    if raw.startswith(codecs.BOM_UTF8):
        raw = raw.replace(codecs.BOM_UTF8, '', 1)

    # Write to file
    file_open = open(file_path, 'w')
    file_open.write(raw)
    file_open.close()
    return 0

1643559367 800 Konvertieren Sie UTF 8 mit BOM in UTF 8 ohne BOM in
Alt.Schlüssel

Ich habe diese Frage gefunden, weil ich Probleme mit habe configparser.ConfigParser().read(fp) beim Öffnen von Dateien mit UTF8-BOM-Header.

Für diejenigen, die nach einer Lösung suchen, um den Header zu entfernen, damit ConfigPhaser die Konfigurationsdatei öffnen kann, anstatt einen Fehler zu melden von:
File contains no section headersöffnen Sie bitte die Datei wie folgt:

configparser.ConfigParser().read(config_file_path, encoding="utf-8-sig")

Dies könnte Ihnen jede Menge Aufwand ersparen, da das Entfernen des BOM-Headers der Datei unnötig wird.

(Ich weiß, das klingt zusammenhangslos, aber hoffentlich könnte das Leuten helfen, die wie ich kämpfen.)

  • da ich zuerst mit try gearbeitet habe – außer –> Dies öffnet auch UTF-8 “not BOM” codierte Dateien ohne Probleme

    – flipSTAR

    7. Oktober 20 um 14:08 Uhr

1643559368 222 Konvertieren Sie UTF 8 mit BOM in UTF 8 ohne BOM in
dokman

Sie können Codecs verwenden.

import codecs
with open("test.txt",'r') as filehandle:
    content = filehandle.read()
if content[:3] == codecs.BOM_UTF8:
    content = content[3:]
print content.decode("utf-8")

  • da ich zuerst mit try gearbeitet habe – außer –> Dies öffnet auch UTF-8 “not BOM” codierte Dateien ohne Probleme

    – flipSTAR

    7. Oktober 20 um 14:08 Uhr

.

703010cookie-checkKonvertieren Sie UTF-8 mit BOM in UTF-8 ohne BOM in Python

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy