Es gab in meinem Leben bisher nichts, womit ich so viel Zeit verschwendet habe wie mit Encoding Problemen.
Für mein aktuelles Projekt entwickle ich zur Zeit einen crawler, der Websites zieht und analysiert. Natürlich bin ich da direkt auf sämtliche Encoding-Problemchen gestoßen, die man sich nur vorstellen kann und hatte unglaublich viel Spaß damit …
Ich verwende das Zend Framework und daher entsprechend die Klasse Zend_Http_Client um die HTTP-Requests abzusetzen.
Danach suche ich den Inhalt der Seite raus, sodass lediglich ein String ohne HTML-Tags und damit reinem Text übrig bleibt.
Gebe ich mir diesen nun einfach auf die Shell aus, stimmt das Encoding manchmal und manchmal nicht. Das sieht man dann immer schön an den kaputten Umlauten.
Die letzten Tage habe ich rund 20 Stunden damit verbracht eine Funktion zu schreiben, welche dafür sorgt, dass der String, der am Ende rauskommt, sauber dargestellt wird – unabhängig davon, was rein kommt. Das Problem hier war in erster Linie, dass selbst Strings, die sich als UTF-8 ausgegeben haben und von denen sogar mb_check_encoding() behauptet hat, es sei alles in bester Ordnung, haben kaputte Umlaute mit sich getragen. Also darauf konnte man sich schonmal gar nicht verlassen.
Ich möchte hier das Ergebnis meiner Arbeit mit euch teilen. Nicht erschrecken, es ist keine saubere Lösung (die sauberen Implementierungen haben allesamt nicht funktioniert). Der Code deckt auch nicht alle denkbaren Fälle ab, aber ich konnte bisher jeden beliebigen kaputten String mit deutschem Text und explodierten Umlauten in einen lesbaren String mit intakten Umlauten konvertieren. Da das mehrere 100 Texte aus verschiedensten Quellen aus dem Netz waren, behaupte ich mal, dass der Code recht brauchbar ist. Im Zweifelsfall dient er als gute Basis für eine umfassendere Implementierung.
Der Methode magicFixStringEncoding() kann man also einen beliebigen String übergeben unabhängig davon ob er völlig in Ordnung ist oder total verstümmelt. Die Rückgabe der Methode sollte immer einen sauberen String mit funktionierenden Umlauten entsprechen.
Für Verbesserungsvorschläge bin ich jeder Zeit offen. Annsonsten viel Spaß denen, die den Code gebrauchen können
class ITWS_Tool {
public static function magicFixStringEncoding($strInput) {
if (preg_match('/[üäöÄÖÜß]/i', $strInput) === 1) {
$strInput = self::convertEncoding($strInput, 'UTF-8');
if (strlen(utf8_decode($strInput)) !== strlen(utf8_decode(utf8_decode($strInput)))) {
$strInput = utf8_decode($strInput);
}
} else {
$strInput = self::convertEncoding($strInput, 'UTF-8', 'ISO-8859-15');
}
return $strInput;
}
public static function convertEncoding($strInput, $toEncoding, $fromEncoding = '') {
if ($fromEncoding == '') {
$fromEncoding = mb_detect_encoding($strInput, array('UTF-8', 'ASCII', 'ISO-8859-1', 'JIS', 'EUC-JP', 'SJIS'), true);
}
if ($fromEncoding == $toEncoding) {
return $strInput;
}
return mb_convert_encoding($strInput, $toEncoding, $fromEncoding);
}
}

