2009-01-31 13 views
11

J'ai un objet chaîneComment convertir (translittérer) une chaîne de utf8 en ASCII (un seul octet) dans C#?

« avec de multiples personnages et même des caractères spéciaux »

Je suis en train d'utiliser

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

objets afin de convertir cette chaîne ascii. Puis-je demander à quelqu'un d'apporter de la lumière à cette tâche simple, c'est de chasser mon après-midi.

EDIT 1: Ce que nous essayons d'accomplir est de se débarrasser des caractères spéciaux comme certaines des fenêtres spéciales apostrophes. Le code que j'ai posté ci-dessous comme réponse ne prendra pas soin de cela. Fondamentalement

O'Brian deviendra O? Brian. où 'est l'une des apostrophes spéciales

+0

Notez que si vous voulez remplacer les caractères accentués avec leurs équivalents non accentuées, vous pouvez utiliser str.Normalize (NormalizationForm.FormKD) – yoyo

Répondre

19

C'était en réponse à votre autre question, qui semble avoir été supprimée ... le point est toujours d'actualité. Il semblerait qu'un classic Unicode to ASCII issue. L'astuce serait de trouver ça se passe.

.NET fonctionne correctement avec Unicode, en supposant it's told it's Unicode pour commencer (ou à gauche par défaut).

Mon devinez est que votre application de réception ne peut pas le gérer. Donc, je serais probablement utiliser la ASCIIEncoderwith un EncoderReplacementFallback avec 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)); 

Bien sûr, dans les vieux jours, nous avions boucle juste bien et supprimer CARactère greater than 127 ... eh bien, ceux de nous aux États-Unis au moins. ;)

+4

Merci, cela a fonctionné parfaitement. Je devais juste faire un petit changement. Encoding encoder = ASCIIEncoding.GetEncoding ("us-ascii", nouveau EncoderReplacementFallback (string.Empty), new DecoderExceptionFallback()); – Geo

+0

+1 pour EncoderReplacementFallback - Je n'avais jamais entendu parler de ça auparavant. Aimer. –

+0

'EncoderReplacementFallback' avec un point d'interrogation est la valeur par défaut. Dans ce cas, il semble qu'une «meilleure perte» est souhaitable. Une exception de secours est utile lorsque la perte est intolérable (qui à mon humble avis devrait être la valeur par défaut). –

12

J'ai été capable de le comprendre. Dans le cas où quelqu'un veut savoir ci-dessous le code qui a fonctionné pour moi:

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

Laissez-moi savoir s'il y a un moyen plus simple o le faire.

+0

Il convient de noter que si la chaîne contient des caractères qui ne peuvent pas être représentés en ASCII, ce ne sera pas la même chaîne après la conversion. Il pourrait manquer ces caractères ou il pourrait devenir brouillé, selon comment Encoding.Convert fonctionne (que je ne sais pas). –

+0

En fait, je viens de tester quelques scénarios et ce que vous dites est vrai. Savez-vous comment surmonter cette limitation. Par exemple si j'ai l'un des apostrophes spéciales pour le remplacer par le commun. – Geo

7

Pour ceux qui aiment les méthodes d'extension, celui-ci fait l'affaire pour nous.

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; 
     } 
    } 
} 

(espace de noms de système il est donc disponible à peu près automatiquement pour toutes nos chaînes.)

5

Sur la base de la réponse de Marc ci-dessus (et commentaire Geo), je créé une version deux doublure pour enlever tous les cas d'exception ASCII à partir d'une chaîne. Fourni aux personnes recherchant cette réponse (comme je l'ai fait).

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 vous souhaitez une représentation en 8 bits des caractères utilisés dans de nombreux codages, cela peut vous aider.

Vous devez modifier la variable targetEncoding selon le codage souhaité.

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);