Corrigiendo errores de detección de codificación cirílica en C# con Ude
La biblioteca Ude en C# a veces identifica incorrectamente la codificación de archivos de texto que contienen caracteres cirílicos, reportando erróneamente 'Macintosh' en lugar de Windows-1251. Esto provoca texto corrupto al leerlo—lo que debería ser ruso legible aparece como 'mojibake' ilegible. El problema se manifiesta tanto en Notepad++ como en código que utiliza CharsetDetector.
En el método GetFileEncoding, Ude devuelve cdet.Charset como 'Macintosh', lo que causa errores durante la conversión posterior:
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);
}
Aplicar esta codificación incorrecta en ChangeEncodingForMidFile agrava el problema: el texto se lee de forma inadecuada y se escribe en un nuevo archivo con corrupción.
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);
}
Analizando las diferencias entre MacCirílico y Windows-1251
Las codificaciones MacCirílico (CodePages.Macintosh) y Windows-1251 utilizan rangos de bytes diferentes para los caracteres cirílicos. Para textos rusos típicos sin símbolos raros, podemos identificar "bytes sospechosos" que son poco característicos de una codificación pero comunes en la otra:
- Sospechosos para Macintosh: Bytes típicos de Windows-1251 (0xAB, 0xB8–0xB9, 0xBB, 0xC0–0xC7, 0xC9, 0xCB–0xCF, 0xD2–0xDB, 0xFF).
- Sospechosos para Windows-1251: Bytes típicos de Macintosh (0x80–0x8F, 0x90–0x97, 0x99–0x9F).
Estos conjuntos se usan para una revalidación heurística.
private static readonly ArrayList<byte> StrangeForMacintochBytes = 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
};
Implementando CustomGetEncoding
El método CustomGetEncoding se activa cuando se detecta Macintosh o MacCirílico:
if (cdet.Charset != null)
{
var encoding = Encoding.GetEncoding(cdet.Charset);
if (encoding.CodePage == CodePages.Macintoch || encoding.CodePage == CodePages.MacCyrillic)
return CustomGetEncoding(encoding, filename);
}
Lógica de CustomGetEncoding:
- Escanea los bytes del archivo.
- Si se encuentra un byte de
StrangeForMacintochBytes— devuelve Windows-1251. - Si no, pero hay un byte de
StrangeForWindows1251Bytes— devuelve Macintosh. - Si no hay bytes sospechosos — por defecto devuelve Windows-1251.
Esto resuelve el caso para textos rusos básicos, pero no es aplicable universalmente.
Limitaciones y recomendaciones
Desventajas de este enfoque:
- Solo funciona con textos cirílicos sin caracteres raros.
- No maneja UTF-8 ni otras codificaciones.
- Depende de heurísticas, no de un mecanismo confiable de detección.
Para usuarios:
- Abre el archivo en Notepad++.
- Prueba diferentes codificaciones (Windows-1251, UTF-8) hasta que no haya corrupción.
- Copia el texto.
- Crea un nuevo archivo con la codificación objetivo y pégalo.
- Guárdalo.
Incluso este trabajo manual no garantiza un 100% de éxito si Ude identifica mal la codificación, a pesar de que el texto se ve correcto visualmente.
Otras bibliotecas de detección de codificación presentan problemas similares. La detección automática es inherentemente probabilística y depende de patrones de frecuencia de bytes en el texto.
Conclusiones clave
- Ude suele confundir MacCirílico y Windows-1251 en archivos cirílicos.
- Usar heurísticas basadas en "bytes sospechosos" corrige la detección sin modificar la biblioteca.
- La solución solo funciona para textos rusos básicos.
- Siempre verifica manualmente la codificación en Notepad++ antes de procesar.
- La detección de codificación es probabilística: los errores son inevitables.
— Editorial Team
Aún no hay comentarios.