Beat: Change Encoding (Bitte u Code Reveiw)

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

--
><o(((°>           ><o(((°>
   <°)))o><                     ><o(((°>o
Der Valigator leibt diese Fische
  1. Tach,

    Die Aufgabe ist, das Encoding einer Liste von Files zu ändern.

    gibt es einen Grund, warum du nicht einfach iconv/uconv nutzt?

    mfg
    Woodfighter

    1. 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.

      mfg Beat

      --
      ><o(((°>           ><o(((°>
         <°)))o><                     ><o(((°>o
      Der Valigator leibt diese Fische
      1. 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

        1. 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

          --
          ><o(((°>           ><o(((°>
             <°)))o><                     ><o(((°>o
          Der Valigator leibt diese Fische
      2. Ja. Alles was nicht Linux ist.

        http://perldoc.perl.org/piconv.html funktionert bei mir auch unter windows.

        Struppi.

  2. 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

    1. $chr = printf("%s", pack("U", $cp)); # nicht $c!!!

      sprintf ;-)