Letras alemanas y encoding en C #

Tengo una función de descompresión, y estoy usando System.Text.Encoding para asegurarme de que los archivos que se están extrayendo conservan los mismos nombres después de la extracción porque generalmente los archivos que estoy descomprimiendo contienen letras en alemán.
äÄéöÖüß.txt diferentes cosas como Encoding.Default o Encoding.UTF8 pero nada funciona äÄéöÖüß.txt se convierte a „Ž‚”™á.txt o, en caso de que sea el valor predeterminado, son recuadros negros: /

¿alguna sugerencia?

 using (ZipArchive archive = System.IO.Compression.ZipFile.Open(ZipFile, ZipArchiveMode.Read, System.Text.Encoding.Default)) { foreach (ZipArchiveEntry entry in archive.Entries) { string fullPath = Path.Combine(appPath, entry.FullName); if (String.IsNullOrEmpty(entry.Name)) { Directory.CreateDirectory(fullPath); } else { if (!entry.Name.Equals("Updater.exe")) { entry.ExtractToFile(fullPath,true); } } } } 

Prueba CodePage 850 (me ha funcionado):

 using (ZipArchive archive = System.IO.Compression.ZipFile.Open(ZipFile, ZipArchiveMode.Read, System.Text.Encoding.GetEncoding(850))) { // .... 

El siguiente comentario es de (una versión antigua) de Sharpziplib que me puso en la dirección correcta:

  /* Using the codepage 1252 doesn't solve the 8bit ASCII problem :/ any help would be appreciated. // get encoding for latin characters (like ö, ü, ß or ô) static Encoding ecp1252 = Encoding.GetEncoding(1252); */ // private static Encoding _encoding = System.Text.ASCIIEncoding; private static Encoding _encoding = System.Text.Encoding.GetEncoding(850); 

La última línea es mi cambio, para que lea correctamente los archivos zip con caracteres especiales.

En primer lugar, el único formato ZIP oficial (no existente …) no permite caracteres Unicode (entonces no puede usar ninguna otra encoding que no sea ASCII).

Dicho esto, muchas herramientas y bibliotecas le permiten usar una encoding diferente, pero puede fallar (por ejemplo, si intenta decodificar forzando UTF8 / UTF32 o lo que sea un archivo codificado con otra encoding).

Si el nombre del archivo está codificado en ASCII, obtendrá la página de códigos de su sistema:

Para los nombres de entrada que contienen solo caracteres ASCII, se establece el indicador de encoding de idioma y se utiliza la página de códigos predeterminada del sistema actual para codificar los nombres de entrada.

No tienes tanto control con las clases .NET sobre este tema. Pero si no especifica una encoding obtendrá un comportamiento predeterminado (UTF8 para códigos fuera de ASCII y la página de códigos actual para ASCII). La mayoría de las veces funciona (si la encoding y la deencoding se han realizado dentro de la misma página de códigos).

¿Cómo evitar esto? No es fácil (porque carecemos de un estándar) pero para resumir:

  • No fuerce la encoding (a menos que esté consumiendo un archivo zip que comprimió con una encoding conocida).
  • El comportamiento predeterminado es bastante bueno en la mayoría de los casos.
  • Para los ZIP codificados en ASCII con caracteres extendidos, confíe en la página de códigos del sistema (debe ser la misma en ambos sistemas).
  • Proporcionar una forma para que el usuario cambie la encoding (no puede verificar qué encoding utiliza la utilidad zip y no hay ningún estándar al respecto). Significa no solo cambiar la encoding (UTF8 / UTF16 o lo que sea) sino también la página de códigos (en caso de que no coincidan). La función GetEncoding le dará el codificador correcto para la página de códigos que especifique).

¿La mejor pista que puedo darte? Confíe en el comportamiento predeterminado (es bastante común), pero proporcione una forma para que los usuarios lo cambien si necesita ser compatible con la mayoría de los ZIP que existen (porque cada uno puede implementarse de una manera diferente), no solo para la encoding sino para página de códigos también. Especialmente , no lo fuerce desde el código con la página de códigos específica alemana, ya que se romperá con el primer archivo español / francés / italiano / holandés que manejará (y no hay una página de códigos común para ellos).

Por cierto, prepárese para manejar varias excepciones si abre un archivo con una encoding incorrecta (no una página de códigos).

Edición para futuros lectores (de los comentarios): CP 850 captura la mayoría de los personajes comunes de Europa Occidental, pero no es la página de códigos para Europa . Compárelo, por ejemplo, con los idiomas de Europa del Este o con el noruego. No los combina (y en ese idioma, los caracteres fuera del rango de 33 a 127 son bastante comunes porque no son dibujos de cajas). Algunos caracteres de CP 850 (por ejemplo, Ê Ë ı ) no están disponibles en (digamos) CP 865 (para el idioma Norsk).

Dejame explicarte con un ejemplo. Tiene un nombre de archivo (de Trukey) con este nombre: “Garip Dosya Adı.txt”. El último carácter tiene el código 141 en CP 857 (para Turquía). Si está utilizando el CP 850, obtendrá ì en lugar de ı porque en el CP 850 original tiene el código 213. Ni siquiera mencionaré los idiomas del Lejano Oriente (porque una página de códigos fijos causará problemas) incluso si está limitado a Europa). Esta es la razón por la que no puede establecer una página de códigos fijos a menos que esté escribiendo una pequeña utilidad para su propio uso.