2009-01-31 59 views
11

Tengo un objeto de cadenaCómo convertir (transcribir) una cadena de utf8 a ASCII (byte único) en C#?

"con múltiples caracteres y caracteres especiales" incluso

Estoy tratando de utilizar

UTF8Encoding utf8 = new UTF8Encoding(); 
ASCIIEncoding ascii = new ASCIIEncoding(); 

objetos con el fin de convertir esa cadena en ASCII. ¿Puedo pedirle a alguien que aclare algo sobre esta simple tarea, que es cazar mi tarde?

EDITAR 1: Lo que estamos tratando de lograr es deshacernos de caracteres especiales como algunos de los apóstrofos especiales de Windows. El código que publiqué a continuación como respuesta no se encargará de eso. Básicamente

O'Brian se convertirá en O? Brian. donde 'es uno de los apóstrofos especiales

+0

Tenga en cuenta que si desea reemplazar los caracteres acentuados con sus equivalentes acentuadas, puede utilizar str.Normalize (NormalizationForm.FormKD) – yoyo

Respuesta

19

Esto fue en respuesta a su otra pregunta, parece que se ha eliminado ... el punto sigue en pie.

Parece un classic Unicode to ASCII issue. El truco sería encontrar donde está ocurriendo.

.NET funciona bien con Unicode, suponiendo it's told it's Unicode para empezar (o se deja en el valor predeterminado).

Mi supongo es que su aplicación receptora no puede manejarlo. Por lo tanto, probablemente me uso el ASCIIEncoderwith un EncoderReplacementFallback con String.Empty:

using System.Text; 

string inputString = GetInput(); 
var encoder = ASCIIEncoding.GetEncoder(); 
encoder.Fallback = new EncoderReplacementFallback(string.Empty); 

byte[] bAsciiString = encoder.GetBytes(inputString); 

// Do something with bytes... 
// can write to a file as is 
File.WriteAllBytes(FILE_NAME, bAsciiString); 
// or turn back into a "clean" string 
string cleanString = ASCIIEncoding.GetString(bAsciiString); 
// since the offending bytes have been removed, can use default encoding as well 
Assert.AreEqual(cleanString, Default.GetString(bAsciiString)); 

Por supuesto, en los viejos tiempos, que acababa de bucle sin embargo y eliminar cualquier caracteres greater than 127 ... bueno, los de nosotros en los Estados Unidos al menos. ;)

+4

Gracias funcionó perfectamente. Solo tuve que hacer un pequeño cambio. Encoding encoder = ASCIIEncoding.GetEncoding ("us-ascii", nuevo EncoderReplacementFallback (string.Empty), nuevo DecoderExceptionFallback()); – Geo

+0

+1 para EncoderReplacementFallback - Nunca había escuchado eso antes. Quiéralo. –

+0

'EncoderReplacementFallback' con un signo de interrogación es el valor predeterminado. En este caso, parece deseable una "mejor pérdida". Una excepción de reserva es útil cuando la pérdida es intolerable (que en mi humilde opinión debería ser la predeterminada). –

12

Pude resolverlo. En caso de que alguien quiere saber por debajo del código que funcionó para mí:

ASCIIEncoding ascii = new ASCIIEncoding(); 
byte[] byteArray = Encoding.UTF8.GetBytes(sOriginal); 
byte[] asciiArray = Encoding.Convert(Encoding.UTF8, Encoding.ASCII, byteArray); 
string finalString = ascii.GetString(asciiArray); 

Avísame si hay una manera más sencilla o haciéndolo.

+0

Vale la pena señalar que si la cadena contiene caracteres que no pueden ser representados en ASCII, no será la misma cadena después de la conversión. Es posible que le falten esos caracteres o podría distorsionarse, dependiendo de cómo funcione Encoding.Convert (que no sé). –

+0

En realidad acabo de probar algunos escenarios y lo que dices es cierto. ¿Sabes cómo superar esta limitación? Por ejemplo, si tengo uno de los apóstrofes especiales para reemplazarlo por uno común. – Geo

7

Para cualquiera a quien le gusten los métodos de extensión, este es el truco para nosotros.

using System.Text; 

namespace System 
{ 
    public static class StringExtension 
    { 
     private static readonly ASCIIEncoding asciiEncoding = new ASCIIEncoding(); 

     public static string ToAscii(this string dirty) 
     { 
      byte[] bytes = asciiEncoding.GetBytes(dirty); 
      string clean = asciiEncoding.GetString(bytes); 
      return clean; 
     } 
    } 
} 

(espacio de nombres System para que esté disponible más o menos automáticamente para todas nuestras cadenas.)

5

Sobre la base de la respuesta de la marca anterior (y de comentario Geo), que creó una versión de dos forro para eliminar todos los casos de excepción ASCII de una cuerda. Proporcionado para las personas que buscan esta respuesta (como yo lo hice).

using System.Text; 

// Create encoder with a replacing encoder fallback 
var encoder = ASCIIEncoding.GetEncoding("us-ascii", 
    new EncoderReplacementFallback(string.Empty), 
    new DecoderExceptionFallback()); 

string cleanString = encoder.GetString(encoder.GetBytes(dirtyString)); 
1

Si desea una representación de 8 bits de los caracteres que se utilizan en muchas codificaciones, esto puede ayudarlo.

Debe cambiar la variable targetEncoding a la codificación que desee.

Encoding targetEncoding = Encoding.GetEncoding(874); // Your target encoding 
Encoding utf8 = Encoding.UTF8; 

var stringBytes = utf8.GetBytes(Name); 
var stringTargetBytes = Encoding.Convert(utf8, targetEncoding, stringBytes); 
var ascii8BitRepresentAsCsString = Encoding.GetEncoding("Latin1").GetString(stringTargetBytes); 
Cuestiones relacionadas