7 Stimmen

Wie kann ich UTF-16-Daten in Perl dekodieren, wenn ich die Bytereihenfolge nicht kenne?

Wenn ich eine Datei öffne ( und direkt eine Kodierung angebe ) :

open(my $file,"<:encoding(UTF-16)","some.file") || die "error $!\n";
while(<$file>) {
    print "$_\n";
}
close($file);

Ich kann den Inhalt der Datei gut lesen. Allerdings, wenn ich tun:

use Encode;

open(my $file,"some.file") || die "error $!\n";
while(<$file>) {
    print decode("UTF-16",$_);
}
close($file);

Ich erhalte den folgenden Fehler:

UTF-16:Unrecognised BOM d at F:/Perl/lib/Encode.pm line 174

Wie kann ich es mit decode ?

EDIT: Hier sind die ersten paar Bytes:

FF FE 3C 00 68 00 74 00

12voto

brian d foy Punkte 124323

Wenn Sie einfach "UTF-16" angeben, sucht Perl nach dem Byte-Order-Mark (BOM), um herauszufinden, wie es zu parsen ist. Wenn es kein BOM gibt, wird es explodieren. In diesem Fall müssen Sie Encode mitteilen, welche Bytereihenfolge Sie haben, indem Sie entweder "UTF-16LE" für Little-Endian oder "UTF-16BE" für Big-Endian angeben.

Es gibt noch etwas anderes, was in Ihrer Situation vor sich geht, aber es ist schwer zu sagen, ohne die Daten in Ihrer Datei zu sehen. Ich erhalte den gleichen Fehler mit beiden Snippets. Wenn ich keine Stückliste habe und keine Bytereihenfolge angebe, beschwert sich mein Perl so oder so. Welches Perl verwenden Sie und welche Plattform haben Sie? Gibt es auf Ihrer Plattform die native Endianness Ihrer Datei? Ich denke, das Verhalten, das ich sehe, ist laut der Dokumentation korrekt.

Außerdem können Sie nicht einfach eine Zeile in einer unbekannten Kodierung lesen (was auch immer Perls Standard ist) und diese dann an decode . Sie könnten in der Mitte einer Multi-Byte-Sequenz landen. Sie müssen Encode::FB_QUIET um den Teil des Puffers zu speichern, den Sie nicht dekodieren konnten, und ihn zum nächsten Datenpaket hinzuzufügen:

open my($lefh), '<:raw', 'text-utf16.txt';

my $string;
while( $string .= <$lefh> ) {
    print decode("UTF-16LE", $string, Encode::FB_QUIET) 
    }

6voto

Snake Plissken Punkte 668

Sie müssen entweder UTF-16BE oder UTF-16LE angeben. Siehe http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM

1voto

mscha Punkte 6302

Was du versuchst, ist unmöglich.

Sie lesen gerade Zeilen von Text ohne Angabe einer Kodierung, so dass jedes Byte, das ein Zeilenumbruchszeichen enthält (Standard \x0a ) beendet eine Zeile. Dieser Zeilenvorschub kann aber durchaus in der Mitte eines UTF-16-Zeichens stehen, so dass die nächste Zeile nicht dekodiert werden kann. Wenn Ihre Daten UTF-16LE sind, passiert das ständig - Zeilenvorschübe sind \x0a \x00 . Wenn Sie UTF16-BE haben, könnten Sie Glück haben (Zeilenumbrüche sind \x00 \x0a ), bis Sie ein Zeichen mit \x0a im High-Byte.

Tun Sie das also nicht, sondern öffnen Sie die Datei in der richtigen Kodierung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X