2009-10-23 9 views
7

ich schon wissen, wie die Nicht-UTF-8-kodierten Inhalt einer Datei Zeile für Zeile auf UTF-8 zu konvertieren, so etwas wie den folgenden Code:Wie kann ich eine Eingabedatei in UTF-8-Codierung in Perl konvertieren?

# outfile.txt is in GB-2312 encode  
open my $filter,"<",'c:/outfile.txt'; 

while(<$filter>){ 
#convert each line of outfile.txt to UTF-8 encoding 
    $_ = Encode::decode("gb2312", $_); 
...} 

Aber ich denke, Perl das ganze direkt kodieren Eingabedatei in UTF-8-Format, so habe ich versucht, so etwas wie

#outfile.txt is in GB-2312 encode 
open my $filter,"<:utf8",'c:/outfile.txt'; 

(Perl sagt so etwas wie "UTF-8 "\ xD4" Karte nicht auf Unicode")

und

open my $filter,"<",'c:/outfile.txt'; 
$filter = Encode::decode("gb2312", $filter); 

(Perl sagt „Readline-() auf ungeöffnete Dateihandle!)

Sie arbeiten nicht. Aber gibt es eine Möglichkeit, die Eingabedatei direkt in UTF-8 zu konvertieren?

Update:

Sieht aus wie die Dinge nicht so einfach sind, wie ich dachte. Ich kann nun die Eingabedatei über Umwege in UTF-8-Code umwandeln. Ich öffne zuerst die Eingabedatei und dann kodiere den Inhalt davon zu UTF-8 und dann Ausgabe in eine neue Datei und öffne dann die neue Datei für die weitere Verarbeitung. Dies ist der Code:

open my $filter,'<:encoding(gb2312)','c:/outfile.txt'; 
open my $filter_new, '+>:utf8', 'c:/outfile_new.txt'; 
print $filter_new $_ while <$filter>; 
while (<$filter_new>){ 
... 
} 

Aber das ist zu viel Arbeit und es ist sogar noch problematischer als einfach den Inhalt von $ filter zeilen kodieren.

+3

Wenn Sie in einer Frage eine Warnmeldung angeben, fügen Sie die Warnmeldung in die Frage ein. :) –

+0

@brian, danke für den Vorschlag. – Mike

+1

Es ist am besten, die genaue Warnmeldung zu verwenden :) Also, mit dieser Warnung müssen Sie das Ergebnis Ihrer Open überprüfen (was Sie immer tun sollten). –

Antwort

5

Ich glaube, ich habe Ihre Frage missverstanden. Ich denke, was Sie tun möchten, ist eine Datei in einer Nicht-UTF-8-Codierung zu lesen, dann spielen Sie mit den Daten als UTF-8 in Ihrem Programm. Das ist viel einfacher. Nachdem Sie die Daten mit der richtigen Codierung gelesen haben, stellt Perl sie intern als UTF-8 dar. Tue einfach, was du zu tun hast.

Wenn Sie es wieder ausgeben, verwenden Sie die Codierung, die Sie speichern möchten. Sie müssen es jedoch nicht in eine Datei zurücklegen, um es zu verwenden.


alte Antwort

Die Perl-I/O-Schichten lesen die Daten nur unter der Annahme, es ist schon richtig codiert. Es wird nicht die Kodierung für dich konvertieren. Wenn du utf8 öffnest, sagst du, dass es bereits utf8 ist.

Sie müssen das Modul Encode genauso verwenden, wie Sie es gezeigt haben (es sei denn, Sie möchten Ihre eigene I/O-Ebene schreiben). Sie können Bytes in UTF-8 konvertieren, oder wenn Sie die Codierung kennen, können Sie von einer Kodierung in eine andere konvertieren. Da es so aussieht, als ob Sie die Kodierung bereits kennen, möchten Sie vielleicht die from_to() Funktion.

Wenn Sie gerade mit Perl und Unicode beginnen, gehen Sie durch Juerd's Perl Unicode Advice, bevor Sie etwas tun.

+0

@ Brian, danke für die Anleitung. Ich dachte, es sollte eine einfache Möglichkeit geben, die Eingabedatei beim Öffnen direkt in UTF-8 zu konvertieren. Aber jetzt sieht es so aus, als wären die Dinge nicht so einfach. Ich denke, ich kann die Eingabedatei zuerst öffnen und dann den Inhalt in UTF-8 codieren und dann in eine andere Datei in UTF-8-Codierung ausgeben und dann diese andere Datei öffnen. Der Code sieht so aus: öffne meinen $ filter, '<: encoding (gb2312)', 'c: /outfile.txt'; öffne meine $ filter_new, '+>: utf8', 'c: /f2.txt'; print $ filter_new $ _ while <$filter>; while (<$filter_new>) {...} Aber das ist zu viel Arbeit. während (<$fh_out>) { – Mike

+0

Ihre Vorstellung von zu viel Arbeit ist verzerrt. Versuchen Sie es mit der Hand und kommen Sie dann zurück und erzählen Sie uns, wie einfach Perl es für Sie macht. Kinder wissen heute nicht, wie gut sie es haben. :) –

+0

Mikes Instinkte sind korrekt; Sie können Ebenen stapeln, um die Konvertierung direkt zu machen, die er will :) – ysth

4

Der: encoding-Layer gibt UTF-8 zurück, geeignet für Perls Verwendung. Das heißt, Perl erkennt jedes Zeichen als ein Zeichen, selbst wenn es mehrere Bytes sind. Abhängig davon, was Sie als nächstes mit den Daten tun werden, kann dies angemessen sein.

Aber wenn Sie etwas mit den Daten tun, wo Perl versuchen wird, es von UTF8 herunterzustufen, müssen Sie Perl entweder nicht sagen (zum Beispiel einen BinMode (STDOUT, ": utf8"), um Perl das zu sagen output to stdout sollte utf8) sein, oder du musst perl deine utf8 als Binärdaten behandeln (jedes Byte einzeln interpretieren und nichts über die utf8-Zeichen wissen.)

Dafür brauchst du nur ein zusätzliche Schicht auf Ihre offenen:

open my $foo, "<:encoding(gb2312):bytes", ...; 

Beachten Sie, dass die Ausgabe des folgenden werden die gleichen sein:

perl -we'open my $foo, "<:encoding(gb2312):bytes", "foo"; $bar = <$foo>; print $bar' 
perl -CO -we'open my $foo, "<:encoding(gb2312)", "foo"; $bar = <$foo>; print $bar' 

aber in einem Fall, perl weiß, dass Daten lesen ist utf8 (und so lang ($ bar) wird die Anzahl der UTF-8-Zeichen berichtet) und ausdrücklich gesagt werden muss (durch CO), dass STDOUT utf8 akzeptieren und in der anderen macht Perl keine Annahmen über die Daten (und so Länge ($ bar) wird die Anzahl der Bytes), und druckt es nur so aus wie es ist.

Verwandte Themen