Wie kann ich Perl dazu bringen, fehlerhafte UTF-8-Sequenzen zu erkennen?

8

Ich benutze Perl 5.10.0 und Postgres 8.4.3 und Zeichenketten in einer Datenbank, die hinter einer DBIx steht :: Klasse .

Diese Zeichenfolgen sollten in UTF-8 sein, und daher wird meine Datenbank in UTF-8 ausgeführt. Leider sind einige dieser Zeichenfolgen fehlerhaft und enthalten fehlerhaft formatierte UTF-8. Wenn ich sie ausführe, erhalte ich eine Ausnahme

DBI Exception: DBD::Pg::st execute failed: ERROR: invalid byte sequence for encoding "UTF8": 0xb5

Ich dachte, ich könnte einfach die ungültigen ignorieren und mich später wegen der fehlerhaften UTF-8 sorgen, also sollte dieser Code die schlechten Titel markieren und ignorieren.

%Vor%

Perl scheint jedoch zu glauben, dass die Strings gültig sind, aber es löst immer noch die Ausnahmen aus.

Wie kann ich Perl dazu bringen, das schlechte UTF-8 zu erkennen?

    
gorilla 16.04.2010, 22:20
quelle

3 Antworten

8

Bitte beachten Sie zuerst die Dokumentation - das utf8 Modul sollte nur in der 'utf8 benutzen;' Form, um anzuzeigen, dass Ihr Quellcode UTF-8 anstelle von Latin-1 ist. Verwenden Sie keine der utf8-Funktionen.

Perl unterscheidet zwischen Bytes und UTF-8-Strings. Im Byte-Modus weiß Perl nicht, welche Kodierung Sie verwenden und verwendet Latin-1, wenn Sie es drucken. Nimm zum Beispiel das Eurozeichen (€). In UTF-8 sind dies 3 Bytes, 0xE2, 0x82, 0xAC. Wenn Sie die Länge dieser Bytes drucken, wird Perl 3 zurückgeben. Auch hier ist die Codierung nicht wichtig. Es kann irgendwelche Bytes oder irgendeine Kodierung sein, legal oder illegal.

Wenn Sie das Modul Encode verwenden und Encode::decode("UTF-8', $bytes) aufrufen, erhalten Sie eine neue Zeichenkette, bei der das sogenannte UTF8-Flag gesetzt ist. Perl weiß nun, dass Ihre Zeichenfolge in UTF-8 ist, und gibt eine Länge von 1 zurück.

Das Problem, dass utf8::valid nur für den zweiten String-Typ gilt. Ihre Zeichenfolgen befinden sich wahrscheinlich in der ersten Form, dem Byte-Modus, und utf8::valid gibt nur true für alles in Byteform zurück. Dies ist in der perldoc dokumentiert.

Die Lösung besteht darin, Perl dazu zu bringen, Ihre Byte-Zeichenfolgen als UTF-8 zu dekodieren und Fehler zu erkennen. Dies kann mit FB_CROAK geschehen, wie brian d foy erklärt:

%Vor%

Sie können diesen Fehler dann abfangen und diese ungültigen Zeichenfolgen überspringen.

Oder wenn Sie wissen, dass Ihr Code meistens UTF-8 mit ein paar ungültigen Sequenzen hier und dort ist, können Sie verwenden:

%Vor%

verwendet den Standardmodus von FB_DEFAULT und ersetzt ungültige Zeichen durch U + FFFD, den Unicode ERSATZCHARAKTER (Raute mit Fragezeichen).

Sie können die Zeichenfolge dann in den meisten Fällen direkt an Ihren Datenbanktreiber übergeben. Bei einigen Treibern müssen Sie die Zeichenfolge möglicherweise zuerst wieder in Byteform umschlüsseln:

%Vor%

Es gibt auch reguläre Ausdrücke, mit denen Sie nach gültigen UTF-8-Sequenzen suchen können, bevor Sie decode aufrufen (überprüfen Sie andere Stack Overflow-Antworten). Wenn Sie diese Regexes verwenden, müssen Sie weder codieren noch dekodieren.

Schließlich verwenden Sie UTF-8 anstatt utf8 in Ihren Aufrufen von decode . Letzteres ist laxer und erlaubt, dass einige ungültige UTF-8-Sequenzen (wie Sequenzen außerhalb des Unicode-Bereichs) durchgelassen werden.

    
rjh 16.04.2010, 22:31
quelle
8

Wie kommst du an deine Fäden? Sind Sie sicher, dass Perl denkt, dass sie bereits UTF-8 sind? Wenn sie noch nicht dekodiert sind (das heißt, Oktette werden als eine Kodierung interpretiert), müssen Sie das selbst tun:

%Vor%

Besser noch, wenn Sie wissen, dass Ihre String-Quelle bereits UTF-8 ist, müssen Sie diese Quelle als UTF-8 lesen. Schauen Sie sich den Code an, der die Zeichenfolgen enthält, um zu sehen, ob Sie das richtig machen.

    
brian d foy 17.04.2010 13:02
quelle
2

Wie die Dokumentation für utf8::valid zeigt, gibt es true zurück, wenn die Zeichenfolge als UTF-8 markiert ist und UTF-8 gültig ist, oder wenn die Zeichenfolge überhaupt nicht UTF-8 ist . Obwohl es unmöglich ist, dies zu erkennen, ohne den Code im Kontext zu sehen und zu wissen, was die Daten sind, ist es höchstwahrscheinlich nicht die "gültige utf8" -Prüfung; Wahrscheinlich musst du nur

machen %Vor%     
hobbs 16.04.2010 22:29
quelle

Tags und Links