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 statt use 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.
InformationsquelleAutor Matt | 2010-12-02
Schreibe einen Kommentar