Change Encoding (Bitte u Code Reveiw)
Beat
- perl
2 Jens Holzkämper0 Beat0 Jens Holzkämper0 Beat
1 Struppi
0 hotti0 hotti
Ich bitte um eine Code Review.
Die Aufgabe ist, das Encoding einer Liste von Files zu ändern.
Zwei Encoding-Transformationen sollen unterstützt werden:
von ISO-8859-X nach UTF-8
von UTF-8 nach ISO-8859-X
Der vorliegende Code wurde aus dem bestehenden programm "as is" kopiert.
Ein paar Kommentare sollen den Inhalt der Variablen zusätzlich erläutern.
Die Prüfung der Übergabeparameter ist bereits erfolgt.
use Encode::Guess;
prt('c','<h4>Konversion von Files in <var class="dir">userdata</var></h4>',
'<p>von Charset: '. $User{multipart}{encode}[0].' nach '.$User{multipart}{encode}[1].'</p>');
my($ntf,$urf,$pf)=('','','');
foreach( keys %{ $Store->{userfile} } ){
#scheide non text Files aus.
$Store->{userfile}{$_}{stat2} eq 'text'
or $ntf.= '<li>'.$Store->{userfile}{$_}{path}.'</li>'
and next;
#scheide Files aus, die ungenügende Rechte besitzen
$Store->{userfile}{$_}{stat1} < 6
and $urf.= '<li>'.$Store->{userfile}{$_}{path}.'</li>'
and next;
my $file;
open( my $rfh, '<', $Store->{userfile}{$_}{path} ) or die("Encoding Conversion: $!");
# slurpmode
{
local $/ = undef;
$file = <$rfh>;
}
close $rfh;
# sortiere Ascii-Files aus.
$file =~ /[\x80-\xff]/
or $pf .= '<li>'.$Store->{userfile}{$_}{path}.'<br>ist in ASCII (keine Konvertierung)</li>'
and next;
# Frage: ist die obige Prüfung statthaft unter der Erwartung
# dass nur UTF-8 oder Iso Encodings erwartet / unterstützt werden?
# $User{multipart}{encode}[0] enthält Quellencoding
# $User{multipart}{encode}[1] enthält Zielencoding
my $guess = guess_encoding($file, $User{multipart}{encode}[0], $User{multipart}{encode}[1]);
ref($guess) #Scalar bei Fehler mit Fehlermessage
or $pf .= '<li>'.$Store->{userfile}{$_}{path}.'<br> ERROR:'.$guess.'</li>'
and next;
my $guess_decoded = $guess->decode($file);
my $decoded = decode( $User{multipart}{encode}[1], $file);
# stelle fest, ob ein File bereits im Zielencoding kodiert ist.
$guess_decoded eq $decoded
and $pf .= '<li>'.$Store->{userfile}{$_}{path}.'<br> ist bereits im Ziel-Encoding.</li>'
and next;
# Nun sollten nur noch Files vorhanden sein, die
# im Quellencoding sind und nicht ASCII Textfiles sind
open( my $wfh, '>:encoding('.$User{multipart}{encode}[1].')', $Store->{userfile}{$_}{path} ) or die("Encoding Conversion: $!");
print $wfh $guess_decoded;
close $wfh;
}
# Protokoll
$ntf and prt('c','<h5>Keine Textfiles</h5>','<ul>',$ntf,'</ul>');
$urf and prt('c','<h5>Ungenügende Rechte</h5>','<ul>',$urf,'</ul>');
$pf and prt('c','<h5>Behandelte Files</h5>','<ul>',$pf,'</ul>');
Zusammenfassend:
Ich lasse mit guess() raten, welches Encoding voriegt. Ist es bereits im Zielencoding (ermittle ich durch explizites decode ) kann ich das File überspringen.
Wenn guess keinen Fehler berichtet hat es andernfalls nun das Quellencoding geraten.
Auf diese Files kann ich nun die gewünschte Konversion anwenden.
Das ganze scheint etwas umständlich. Ich habe aber nichts besseres gefunden.
mfg Beat
Tach,
Die Aufgabe ist, das Encoding einer Liste von Files zu ändern.
gibt es einen Grund, warum du nicht einfach iconv/uconv nutzt?
Ja. Alles was nicht Linux ist.
nicht POSIX-kompatibel zu sein, ist zum Glück kein Hindernis.
mfg
Woodfighter
gibt es einen Grund, warum du nicht einfach iconv/uconv nutzt?
Ja. Alles was nicht Linux ist.
nicht POSIX-kompatibel zu sein, ist zum Glück kein Hindernis.
Für wen?
Es geht hier darum, dass das CMS den Anwender bei einer Zeichensatzmigration assistiert. Das Tool soll innerhalb des CMS zur Verfügung stehen.
mfg Beat
Ja. Alles was nicht Linux ist.
http://perldoc.perl.org/piconv.html funktionert bei mir auch unter windows.
Struppi.
hi,
Ich lasse mit guess() raten, welches Encoding voriegt. Ist es bereits im
Das ist prinzipiell gut, denn wenn eine Datei zweimal umcodiert wird, gibt das einen GAU für den DAU ;-)
Zum Feststellen, ob alle Zeichen einer Datei UTF-8-codiert sind, würde ich so vorgehen:
Eine Liste der Codepoints erstellen
@codepoints = unpack("U*", $file_as_string);
Diese Liste durchgehen und die Codepoints wieder in UTF-8-Chars verwandeln
foreach my $cp(@codepoints){
$chr = printf("%s", pack("U", $cp)); # nicht $c!!!
$test_string .= $chr;
}
Vergleiche $test_string mit $file_as_string, wenn beide gleich, sind alle Zeichen in der Datei utf8-codiert. Ansonsten nicht.
Morgen wird getestet ;-)
Gute Nacht,
Hotti
$chr = printf("%s", pack("U", $cp)); # nicht $c!!!
sprintf ;-)