Cyrillische Zeichencodierung in C# korrigieren: Ude-Fehler beheben
Die Bibliothek Ude erkennt in C# gelegentlich die Codierung von Textdateien mit kyrillischen Zeichen falsch und meldet stattdessen 'Macintosh' anstelle von Windows-1251. Dies führt zu verschobenem Text beim Lesen – russische Texte, die eigentlich lesbar sein sollten, erscheinen als unleserliches 'Mojibake'. Das Problem tritt sowohl in Notepad++ als auch in Code auf, der CharsetDetector nutzt.
In der Methode GetFileEncoding gibt Ude cdet.Charset als 'Macintosh' zurück, was bei nachfolgenden Umwandlungen zu Fehlern führt:
public static Encoding GetFileEncoding(string filename)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
using (FileStream fs = File.OpenRead(filename))
{
Ude.CharsetDetector cdet = new Ude.CharsetDetector();
cdet.Feed(fs);
cdet.DataEnd();
if (cdet.Charset != null)
{
return Encoding.GetEncoding(cdet.Charset);
}
}
return Encoding.GetEncoding(CodePages.Windows1251);
}
Die Anwendung dieser falschen Codierung in ChangeEncodingForMidFile verschärft das Problem: Der Text wird falsch gelesen und in einer neuen Datei mit Beschädigung gespeichert.
private static void ChangeEncodingForMidFile(string midFile,
Encoding midFileEncoding,
string newFullMidFileName)
{
using StreamReader reader = new StreamReader(midFile, midFileEncoding);
using StreamWriter writer = new StreamWriter(
newFullMidFileName,
false,
Encoding.GetEncoding(CodePages.Windows1251)
);
writer.Write(reader.ReadToEnd());
File.Delete(midFile);
File.Move(newFullMidFileName, midFile);
}
Unterschiede zwischen MacCyrillic und Windows-1251 analysieren
Die Codierungen MacCyrillic (CodePages.Macintosh) und Windows-1251 verwenden unterschiedliche Byte-Bereiche für kyrillische Zeichen. Für typische russische Texte ohne seltene Symbole können wir "verdächtige" Bytes identifizieren, die für eine Codierung untypisch sind, aber für die andere charakteristisch sind:
- Verdächtig für Macintosh: Bytes, die typisch für Windows-1251 sind (0xAB, 0xB8–0xB9, 0xBB, 0xC0–0xC7, 0xC9, 0xCB–0xCF, 0xD2–0xDB, 0xFF).
- Verdächtig für Windows-1251: Bytes, die typisch für Macintosh sind (0x80–0x8F, 0x90–0x97, 0x99–0x9F).
Diese Mengen dienen zur heuristischen Überprüfung.
private static readonly ArrayList<byte> StrangeForMacintoshBytes = new ArrayList<byte>
{
0xAB,
0xB8, 0xB9, 0xBB,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC9, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
0xFF
};
private static readonly ArrayList<byte> StrangeForWindows1251Bytes = new ArrayList<byte>
{
0x80, 0x81, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
};
Benutzerdefinierte Codierungserkennung implementieren
Die Methode CustomGetEncoding wird ausgelöst, wenn Macintosh oder MacCyrillic erkannt wird:
if (cdet.Charset != null)
{
var encoding = Encoding.GetEncoding(cdet.Charset);
if (encoding.CodePage == CodePages.Macintosh || encoding.CodePage == CodePages.MacCyrillic)
return CustomGetEncoding(encoding, filename);
}
Logik von CustomGetEncoding:
- Durchsuche die Bytes der Datei.
- Wenn ein Byte aus
StrangeForMacintoshBytesgefunden wird – gib Windows-1251 zurück. - Andernfalls, wenn ein Byte aus
StrangeForWindows1251Bytesgefunden wird – gib Macintosh zurück. - Falls keine verdächtigen Bytes gefunden werden – standardmäßig Windows-1251.
Dies löst den Fall für einfache russische Texte, ist aber nicht universell anwendbar.
Grenzen und Empfehlungen
Nachteile dieses Ansatzes:
- Beschränkt auf kyrillische Texte ohne seltene Zeichen.
- Behandelt UTF-8 oder andere Codierungen nicht.
- Beruht auf Heuristiken, kein zuverlässiger Erkennungsmechanismus.
Für Nutzer:
- Öffne die Datei in Notepad++.
- Probiere verschiedene Codierungen (Windows-1251, UTF-8), bis keine Verzerrung mehr auftritt.
- Kopiere den Text.
- Erstelle eine neue Datei mit der Ziel-Codierung und füge den Inhalt ein.
- Speichere sie ab.
Auch diese manuelle Lösung garantiert nicht zu 100 % Erfolg, falls Ude die Codierung dennoch falsch erkennt, obwohl der Text visuell korrekt erscheint.
Andere Bibliotheken zur Zeichencodierungserkennung zeigen ähnliche Probleme. Die automatische Erkennung ist grundsätzlich probabilistisch und hängt von Byte-Häufigkeitsmustern im Text ab.
Wichtige Erkenntnisse
- Ude verwechselt häufig MacCyrillic und Windows-1251 bei kyrillischen Dateien.
- Die Nutzung von "verdächtigen Bytes" als Heuristik behebt die Erkennung, ohne die Bibliothek zu ändern.
- Die Lösung funktioniert nur für grundlegende russische Texte.
- Überprüfe immer die Codierung manuell in Notepad++ vor der Verarbeitung.
- Zeichencodierungserkennung ist probabilistisch – Fehler sind unvermeidlich.
— Editorial Team
Noch keine Kommentare.