2016-04-07 19 views
0

Ich bin mit all diesen verwirrenden Kodierung Sachen stecken. Ich habe eine Datei mit chinesischen Subs. Ich glaube tatsächlich, dass es UTF-8 ist, weil ich dies in Notepad ++ benutze, gibt mir ein sehr gutes Ergebnis. Wenn ich gb2312 setze, ist der chinesische Teil immer noch in Ordnung, aber ich werde sehen, dass ein UTF8-Code nicht konvertiert wird.Wie lese ich chinesische Dateien?

Ziel ist es, den Text in der Datei zu durchlaufen und zu zählen, wie oft die verschiedenen Zeichen angezeigt werden.

import os 
import re 
import io 

character_dict = {} 
for dirname, dirnames, filenames in os.walk('.'): 
    for filename in filenames: 
     if "srt" in filename: 
      import codecs 
      f = codecs.open(filename, 'r', 'gb2312', errors='ignore') 
      s = f.read() 

      # deleting {} 
      s = re.sub('{[^}]+}', '', s) 
      # deleting every line that does not start with a chinese char 
      s = re.sub(r'(?m)^[A-Z0-9a-z].*\n?', '', s) 
      # delete non chinese chars 
      s = re.sub(r'[\s\.A-Za-z0-9\?\!\\/\-\"\,\*]', '', s) 
      #print s 
      s = s.encode('gb2312') 
      print s 
      for c in s: 
       #print c 
       pass 

Dies wird tatsächlich den vollständigen chinesischen Text geben. Aber wenn ich die Schleife auf der Unterseite drucke, bekomme ich nur Fragezeichen anstelle der einzelnen Zeichen.

Auch ich sagte, es ist UTF8, aber ich muss gb2312 für die Codierung und als Einstellung in meinem Gnome-Terminal verwenden. Wenn ich es im Code auf UTF8 setze, bekomme ich nur Müll, egal, ob ich mein Terminal auf UTF8 oder Gb2312 setze. Vielleicht ist diese Datei doch nicht UTF8 !?

In jedem Fall enthält s den vollständigen chinesischen Text. Warum kann ich das nicht tun?

Bitte helfen Sie mir, dies zu verstehen. Es ist sehr verwirrend für mich und die Ärzte bringen mich nirgendwohin. Und Google führt mich zu ähnlichen Problemen, die jemand löst, aber es gibt bisher keine Erklärung, die mir geholfen hat, das zu verstehen.

+1

also ist es gb2312 oder UTF-8? Wenn es UTF-8 ist, warum stellen Sie die Kodierung nicht in 'open()' statt in 'gb2312'? So wie es aussieht, macht diese Frage keinen Sinn –

+0

Es ist ** nicht ** UTF-8, es ist [GB2313] (https://en.wikipedia.org/wiki/GB_2312). Sowohl UTF-8 als auch GB2313 sind * encodings *, eine Möglichkeit, Zeichen in Bytes zu codieren. Verwechseln Sie UTF-8 möglicherweise mit dem Unicode-Standard? –

+0

Ja, @MartijnPieters - Ich kenne den Unterschied und weiß auch, dass es sich um Kodierungen für verschiedene Zeichensätze handelt. Das OP scheint die beiden Codierungen/Zeichensätze austauschbar zu verwenden> "Ich glaube tatsächlich, dass es UTF-8 ist, weil die Verwendung in Notepad ++ mir ein sehr gutes Ergebnis gibt." –

Antwort

0

Sie drucken einzelne Bytes. GB2312 ist eine Multi-Byte-Codierung, und jeder Codepunkt verwendet 2 Bytes. Wenn diese Bytes einzeln gedruckt werden, wird keine gültige Ausgabe, nein, erzeugt.

Die Lösung ist Codierung nicht von Unicode zu Bytes beim Drucken. Schleife über den Unicode-String statt:

# deleting {} 
s = re.sub('{[^}]+}', '', s) 
# deleting every line that does not start with a chinese char 
s = re.sub(r'(?m)^[A-Z0-9a-z].*\n?', '', s) 
# delete non chinese chars 
s = re.sub(r'[\s\.A-Za-z0-9\?\!\\/\-\"\,\*]', '', s) 
#print s 

# No `s.encode()`! 
for char in s: 
    print char 

Sie konnte kodieren jeweils char chararter individuell:

for char in s: 
    print char 

Aber wenn Sie Ihre Konsole/IDE/Terminal richtig konfiguriert haben, sollten Sie in der Lage sein, direkt zu drucken ohne Fehler, zumal Ihre print s.encode('gb2312) `korrekte Ausgabe produziert.

Sie scheinen auch UTF-8 (eine Codierung) mit der Unicode standard zu verwirren. UTF-8 kann verwendet werden, um Unicode-Daten in Bytes darzustellen. GB2312 ist eine Codierung zu und kann verwendet werden, um eine (Teilmenge von) Unicode-Text in Bytes darzustellen.

Möglicherweise möchten Sie auf Python und Unicode lesen:

+0

Vielen Dank für Ihre Hilfe. Dies führt jedoch dazu, dass "UnicodeEncodeError: 'ascii' Codec das Zeichen u '\ u73b0' nicht an Position 0 codieren kann: Ordnungszahl nicht im Bereich (128)" Irgendeine Idee, was das Problem sein könnte? – JasonTS

+0

@JasonTS: Was druckst du * zu *? Ihr Terminal scheint falsch konfiguriert zu sein, da es nur ASCII akzeptiert, aber Ihr 'print s.encode ('gb2312') 'schlägt vor, dass es stattdessen GB2312 akzeptiert. –

+0

@JasonTS: Sie könnten manuell codieren, indem Sie 'print char.encode ('gb2312')' verwenden, aber Sie sollten das Terminal-Gebietsschema besser korrigieren. Oder ist das eine IDE-Konsole oder Windows? –

0

gb2312 ist eine Multi-Byte-Codierung.Wenn Sie über eine mit ihm codierte Bytefolge iterieren, durchlaufen Sie die Bytes und nicht die Zeichen, die Sie zählen (oder drucken) möchten. Wahrscheinlich möchten Sie Ihre Iteration über die unicode-Zeichenfolge ausführen, bevor Sie sie codieren. Bei Bedarf können Sie die einzelnen Codepunkte (Zeichen) in ihre eigenen Bytestrings für die Ausgabe codieren:

# don't do s = s.encode('gb2312') 
for c in s:  # iterate over the unicode codepoints 
    print c.encode('gb2312') # encode them individually for output, if necessary 
+0

Danke, es klappt endlich! Kann ich diese jetzt als Diktatschlüssel verwenden? – JasonTS

+0

Ja, Sie können die 'c' Codepunkte verwenden, die Sie in der Schleife als Dictionary-Schlüssel erhalten. Ich nehme an, Sie könnten auch codierte Versionen von ihnen verwenden, aber ich denke nicht, dass es jemals einen guten Grund dafür geben wird. Es ist viel besser, "Unicode" -Objekte für Text überall in Ihrem Programm zu verwenden, außer wenn Sie Dinge codieren müssen, damit IO richtig funktioniert (z. B. beim Lesen oder Schreiben von Dateien oder Netzwerkdaten oder Drucken auf der Konsole). – Blckknght