Perl: utf8::decode vs. Encode::decode
Ich habe einige interessante Ergebnisse, versuchen zu erkennen, die Unterschiede zwischen der Verwendung Encode::decode("utf8", $var)
und utf8::decode($var)
. Ich habe schon entdeckt, dass das aufrufen der ehemalige mehrmals auf eine variable wird schließlich dazu führen, eine Fehlermeldung "Cannot decode string mit breiten Zeichen in..." in der Erwägung, dass die letztere Methode wird gerne so viele Male, wie Sie möchten, einfach false zurückgeben.
Was ich habe Schwierigkeiten zu verstehen, wie die length
Funktion liefert unterschiedliche Ergebnisse, abhängig davon, welche Methode Sie verwenden, um zu entschlüsseln. Das problem entsteht, weil ich den Umgang mit "doppelt-codiert" utf8-text aus einer externen Datei. Um zu demonstrieren, dieses Problem habe ich eine text-Datei "test.txt" mit den folgenden Unicode-Zeichen auf einer Zeile: U+00e8, U+00ab, U+0086, U+000a. Diese Unicode-Zeichen sind die Doppel-Kodierung der Unicode-Zeichen U+8acb, zusammen mit einem neue-Zeile-Zeichen. Die Datei kodiert wurde, um eine Festplatte in UTF8. Ich führen Sie dann das folgende perl-Skript:
#!/usr/bin/perl
use strict;
use warnings;
require "Encode.pm";
require "utf8.pm";
open FILE, "test.txt" or die $!;
my @lines = <FILE>;
my $test = $lines[0];
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
my @unicode = (unpack('U*', $test));
print "Unicode:\n@unicode\n";
my @hex = (unpack('H*', $test));
print "Hex:\n@hex\n";
print "==============\n";
$test = Encode::decode("utf8", $test);
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
@unicode = (unpack('U*', $test));
print "Unicode:\n@unicode\n";
@hex = (unpack('H*', $test));
print "Hex:\n@hex\n";
print "==============\n";
$test = Encode::decode("utf8", $test);
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
@unicode = (unpack('U*', $test));
print "Unicode:\n@unicode\n";
@hex = (unpack('H*', $test));
print "Hex:\n@hex\n";
Dies gibt die folgende Ausgabe:
Länge: 7 utf8-flag: Unicode: 195 168 194 171 194 139 10 Hex: c3a8c2abc28b0a ============== Länge: 4 utf8-flag: 1 Unicode: 232 171 139 10 Hex: c3a8c2abc28b0a ============== Länge: 2 utf8-flag: 1 Unicode: 35531 10 Hex: e8ab8b0a
Dies ist, was ich erwarten würde. Die Länge ist ursprünglich 7, weil perl denkt, dass $test ist nur eine Folge von bytes. Nach der Entschlüsselung einmal, perl weiß, dass $test ist eine Reihe von Zeichen, die in utf8 codiert (d.h. anstatt eine Länge von 7 bytes, perl gibt eine Länge von 4 Zeichen, auch wenn $test ist noch 7 Byte im Speicher). Nach der zweiten Dekodierung, $test enthält 4 bytes interpretiert als 2-Zeichen, die ist, was ich erwarten würde, da Encode::decode fand die 4-code Punkte und interpretiert Sie als utf8-codierte bytes, was 2 Zeichen. Das merkwürdige ist, wenn ich den code ändern, um call-utf8::decode statt (Ersetze alle $test = Encode::decode("utf8", $test); mit utf8::decode($test))
Diese gibt fast identische Ausgabe, die nur die Folge der Länge unterscheidet:
Länge: 7 utf8-flag: Unicode: 195 168 194 171 194 139 10 Hex: c3a8c2abc28b0a ============== Länge: 4 utf8-flag: 1 Unicode: 232 171 139 10 Hex: c3a8c2abc28b0a ============== Länge: 4 utf8-flag: 1 Unicode: 35531 10 Hex: e8ab8b0a
Scheint es, wie perl ersten zählt die bytes vor der Decodierung (wie erwartet), dann zählt die Zeichen nach der ersten Decodierung, aber dann zählt die bytes wieder nach der zweiten Dekodierung (auch nicht erwartet). Warum würden Sie diesen Schalter passieren? Ist es ein Denkfehler in meinem Verständnis, wie diese decoding-Funktionen arbeiten?
Dank,
Matt
- Irgendeinen Grund, warum Sie
require
ing Modulen stattuse
ing Sie? - Ich habe nicht <code>nutzen</code> utf8, weil damit sagt perl, dass der code selbst ist utf8-codiert, die ich nicht brauchen (perldoc.perl.org/utf8.html). Ich glaube, ich könnte habe <code>nutzen</code>d Kodieren, aber ich bin nur zufällig nicht auf.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie nicht zugelassen für die Nutzung der Funktionen aus der
utf8
pragma-Modul. Die Dokumentation sagt so:Verwenden Sie immer das Encode-Modul, und auch sehen, die Frage Checkliste für die Unicode-Weg mit Perl.
unpack
zu low-level, gibt es nicht, auch geben Sie die Fehler-checking.Du gehst falsch mit der Annahme, dass die octects
E8 AB 86 0A
sind das Ergebnis von UTF-8 Doppel-Codierung die Zeichen諆
undnewline
. Dies ist die Darstellung einer einzelne UTF-8-Codierung dieser Zeichen. Vielleicht die ganze Verwirrung auf Ihrer Seite ergibt sich aus diesem Fehler.length
ist unappropriately überladen, zu bestimmten Zeiten bestimmt es die Länge in Zeichen oder die Länge in Bytes. Verwenden Sie bessere Werkzeuge wieDevel::Peek
.Stellt sich heraus, dies war ein Fehler: https://rt.perl.org/rt3//Public/Bug/Display.html?id=80190.