Unicode

Perl, Unicode und Umlaute in Dateinamen

09. Juni 2022 · Programmierung · andreas · Kein Kommentar

Das Projekt klingt einfach: eine Liste von Dateinamen aus einem Verzeichnis auslesen, in einer Datenbank speichern und zu einem späteren Zeitpunkt anhand der Liste in der Datenbank wieder öffnen. Leider konnte das Skript einige Dateien nicht mehr finden, obwohl diese im Verzeichnis weiterhin vorhanden waren.

Heruntergebrochen auf ein Beispielskript sieht das Szenario wie folgt aus:

test.pl
#!/usr/bin/perl use strict; use warnings; use utf8; use DBI; # remove database unlink("files.sqlite"); # create database from scratch my $dbh = DBI->connect("dbi:SQLite:dbname=files.sqlite", "", "", { sqlite_unicode => 1 }); $dbh->do("CREATE TABLE files (name TEXT);"); # the file to be processed my $filename = "Elternschreiben Änderungen der Regelungen zum Infektionsschutz.pdf"; # create the file in the current directory open(my $fh, ">$filename"); print $fh "TEXT"; close($fh); # read files in current directory opendir(my $dh, "."); while (my $file = readdir($dh)) { next if $file !~ /pdf$/; $file = $dbh->quote($file); $dbh->do("INSERT INTO files (name) VALUES ($file);"); } closedir($dh); # get number of files with name "filename" $filename = $dbh->quote($filename); my $sth = $dbh->prepare("SELECT COUNT(*) AS cnt FROM files WHERE name = $filename;"); $sth->execute; my $row = $sth->fetchrow_hashref; print "found $row->{cnt} file(s).\n"; $sth->finish; $dbh->disconnect();

Statt des erwarteten Ergebnisses “1” ist das Skript jedoch der Meinung, keine passende Datei eingelesen zu haben:

found 0 file(s).

Um Probleme mit der Datenbank auszuschließen, kann das Szenario im Dateisystem nachgebildet werden:

test.pl
#!/usr/bin/perl use strict; use warnings; use utf8; use DBI; # the file to be processed my $filename = "Elternschreiben Änderungen der Regelungen zum Infektionsschutz.pdf"; my $found = 0; # create the file in the current directory open(my $fh, ">$filename"); print $fh "TEXT"; close($fh); # read files in current directory opendir(my $dh, "."); while (my $file = readdir($dh)) { next if $file !~ /pdf$/; if ($file eq $filename) { $found++; } } closedir($dh); print "found $found file(s).\n";

Auch hier wird statt der erwarteten “1” eine “0” für die Menge der gefundenen Dateien ausgegeben.

found 0 file(s).

Einen ersten Hinweis auf die mögliche Ursache bringt die Ausgabe der zu vergleichenden Werte mittels “Data::Dumper”. Während für “$filename” der Wert

$VAR1 = "Elternschreiben \x{c4}nderungen der Regelungen zum Infektionsschutz.pdf";

ausgegeben wird, wird für “$file” der Wert

$VAR1 = 'Elternschreiben Änderungen der Regelungen zum Infektionsschutz.pdf';

ausgegeben, d.h. die Werte der beiden Variablen sind in der internen Repräsentation in Perl tatsächlich unterschiedlich. Mit den richtigen Anhaltspunkten führt eine Suche im Internet zum Stackoverflow-Beitrag “In what encoding does readdir return a filename?” und der dort verlinkten ausführlichen Erklärung.

Des Rätsels Lösung ist die Verwendung von “Encode::decode_utf8”

test.pl
#!/usr/bin/perl use strict; use warnings; use utf8; use DBI; use Encode; # the file to be processed my $filename = "Elternschreiben Änderungen der Regelungen zum Infektionsschutz.pdf"; my $found = 0; # create the file in the current directory open(my $fh, ">$filename"); print $fh "TEXT"; close($fh); # read files in current directory opendir(my $dh, "."); while (my $file = readdir($dh)) { next if $file !~ /pdf$/; if (Encode::decode_utf8($file) eq $filename) { $found++; } } closedir($dh); print "found $found file(s).\n";

dann stimmt auch die Anzahl der gefundenen Dateien mit der erwarteten Anzahl überein:

found 1 file(s).

MySQL, Unicode und die Kommandozeile

08. März 2009 · Anwendungen · andreas · Kein Kommentar

Manchmal können komplizierte Dinge so einfach sein - mit dem richtigen Parameter klappt der Import von Unicode-Dateien problemlos über die MySQL-Kommandozeile:

mysql --default_character_set utf8 datenbank < sql-file

Seltsame Umlaute in phpMyAdmin-Exporten

26. Oktober 2008 · Anwendungen · andreas · Kein Kommentar

Wenn beim Import eines phpMyAdmin-Exports statt der eigentlich erwarteten Umlaute nur seltsame Zeichen angezeigt werden, hilft es, vor dem Import am Anfang der “.sql”-Datei ein

SET NAMES 'utf8';

einzufügen.