substr()

12/08/2012 - 20:11 von Stefan+Usenet | Report spam
Es ist zwar wieder PostgreSQL/Perl, aber das eigentliche Problem scheint
mir hier ganz klar im Bereich Perl zu liegen: nach einem =~ soll einer der
Teilstrings (und davon maximal 128 Zeichen) weiterverwendet werden. Ich
schrieb also:

| [=~]
| $var = substr($1, 0, 128);

...und flog damit zu meinem Erstaunen (nicht konstant reproduzierbar!) auf
die Nase. Nach viel Elimination und Einfuegen von Debug-Statements bin ich
nun an folgendem Punkt angelangt:

| [=~]
| elog(WARNING, unpack('h*', $1));
| $var = substr($1, 0, 128);
| elog(WARNING, unpack('h*', $var));

Rufe ich das Skript 2x hintereinander mit unterschiedlichen Eingangsdaten
auf, dann bekomme ich (bei bestimmten Konstellationen, deren Pattern mir
noch nicht ganz klar ist), dieses Verhalten (der Fehler wird dann bei der
Weiterverarbeitung von $var erzeugt):

| 2012-08-12 20:08:29 CEST WARNING: 4d6172e775732045f16462657267
| 2012-08-12 20:08:29 CEST WARNING: 4d6172e775732045f16462657267
| 2012-08-12 20:08:29 CEST WARNING: 52fc64696765722054686f6d6173
| 2012-08-12 20:08:29 CEST WARNING: 52fc64696765722054686f6d617300
| 2012-08-12 20:08:29 CEST ERROR: invalid byte sequence for encoding "UTF8": 0x00 at line 97.

Klar - die Konvertierung nach utf-8 muss fehlschlagen, wenn ein Null-Byte
im String enthalten ist. Nur: Was bitte _tut_ substr() da um alles in der
Welt? Woher kommt hier das Null-Byte?

Und jetzt, vielleicht sogar noch schlimmer: rufe ich das Skript nur einmal,
mit den fehlerverursachenden Eingangsdaten auf, dann erhalte ich:

| 2012-08-12 20:08:30 CEST WARNING: 52fc64696765722054686f6d6173
| 2012-08-12 20:08:30 CEST WARNING: 52fc64696765722054686f6d6173

...also gerade das, was ich mir in meiner Naivitaet erwartet haette.

Immerhin die nicht-Reproduzierbarkeit ist nun geklaert: beim ersten
Durchlauf sind von rund 800k Datensaetzen ca. 200k fehlerhaft. Beim zweiten
Durchlauf fuehren diese 200k Datensaetze zu rund 50k Fehlern - und so
weiter, und so weiter, bis irgendwann nach zig Durchlaeufen alles korrekt
verarbeitet ist. Aber das kann's ja nicht wirklich sein.

Servus,
Stefan

http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - deftige Liebe, die kaum musiziert.
(Sloganizer)
 

Lesen sie die antworten

#1 Bernd Nawothnig
12/08/2012 - 21:14 | Warnen spam
On 2012-08-12, Stefan Froehlich wrote:
Es ist zwar wieder PostgreSQL/Perl, aber das eigentliche Problem scheint
mir hier ganz klar im Bereich Perl zu liegen: nach einem =~ soll einer der
Teilstrings (und davon maximal 128 Zeichen) weiterverwendet werden. Ich
schrieb also:

| [=~]
| $var = substr($1, 0, 128);

...und flog damit zu meinem Erstaunen (nicht konstant reproduzierbar!) auf
die Nase. Nach viel Elimination und Einfuegen von Debug-Statements bin ich
nun an folgendem Punkt angelangt:

| [=~]
| elog(WARNING, unpack('h*', $1));
| $var = substr($1, 0, 128);
| elog(WARNING, unpack('h*', $var));

Rufe ich das Skript 2x hintereinander mit unterschiedlichen Eingangsdaten
auf, dann bekomme ich (bei bestimmten Konstellationen, deren Pattern mir
noch nicht ganz klar ist), dieses Verhalten (der Fehler wird dann bei der
Weiterverarbeitung von $var erzeugt):

| 2012-08-12 20:08:29 CEST WARNING: 4d6172e775732045f16462657267
| 2012-08-12 20:08:29 CEST WARNING: 4d6172e775732045f16462657267
| 2012-08-12 20:08:29 CEST WARNING: 52fc64696765722054686f6d6173
| 2012-08-12 20:08:29 CEST WARNING: 52fc64696765722054686f6d617300
| 2012-08-12 20:08:29 CEST ERROR: invalid byte sequence for encoding "UTF8": 0x00 at line 97.

Klar - die Konvertierung nach utf-8 muss fehlschlagen, wenn ein Null-Byte
im String enthalten ist. Nur: Was bitte _tut_ substr() da um alles in der
Welt? Woher kommt hier das Null-Byte?



Ich kenne mich mit Perl nun nicht wirklich aus, aber kann es sein,
dass Du bereits auf der UTF-8 Kodierung arbeitest? Dann kannst Du
nàmlich keineswegs einfach starr 128 Bytes abschneiden, weil ein
Zeichen lànger als nur ein Byte sein kann. Das letzte Zeichen ist dann
mit einer gewissen Wahrscheinlichkeit (und das passt zu Deiner
Fehlerbeschreibung) kaputt, weil zwar gemàß UTF-Kodierung noch ein
Byte folgen muss, aber statt dessen das terminierende Null-Byte kommt.




Bernd

"Die Antisemiten vergeben es den Juden nicht, dass die Juden Geist
haben - und Geld." [Friedrich Nietzsche]

Ähnliche fragen