2009-01-31 8 views
11

У меня есть строковый объектКак преобразовать (транслитерировать) строку из utf8 в ASCII (один байт) в C#?

«с несколькими персонажами и даже специальными символами»

Я пытаюсь использовать

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

объектов для того, чтобы преобразовать эту строку в ASCII. Могу ли я попросить кого-нибудь принести свет этой простой задаче, которая охотится днем.

EDIT 1: То, что мы пытаемся достичь, - это избавиться от специальных символов, таких как некоторые специальные апострофы окон. Код, который я написал ниже в качестве ответа, не позаботится об этом. В основном

О'Брайан станет О'Брайан. где «является одним из специальных апострофов

+0

Обрати внимание, что если вы хотите заменить акцентированные символы с их безударных эквивалентами, вы можете использовать str.Normalize (NormalizationForm.FormKD) – yoyo

ответ

19

Это было в ответ на ваш другой вопрос, похоже, что он был удален ... точка все еще стоит.

Похож на classic Unicode to ASCII issue. Трюк должен был бы найти , где это происходит.

.NET работает нормально с Unicode, предполагая it's told it's Unicode для начала (или оставленного по умолчанию).

guess что ваше приложение-получатель не может его обработать. Таким образом, я бы, вероятно, использовать ASCIIEncoderwithEncoderReplacementFallback с 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)); 

Конечно, в старые времена, мы бы просто цикл, хотя и удалите все символы greater than 127 ... ну, те нас в США, по крайней мере. ;)

+4

Спасибо, он отлично работал. Мне просто пришлось немного изменить ситуацию. Encoding encoder = ASCIIEncoding.GetEncoding («us-ascii», новый EncoderReplacementFallback (string.Empty), новый DecoderExceptionFallback()); – Geo

+0

+1 для EncoderReplacementFallback - я никогда не слышал об этом раньше. Любить это. –

+0

«EncoderReplacementFallback» с вопросительным знаком по умолчанию. В этом случае, кажется, желательно «лучше потерять». Исключение исключений полезно, когда потеря недопустима (что ИМХО должно быть по умолчанию). –

12

Я смог выяснить это. В случае, если кто-то хочет знать, ниже код, который работал для меня:

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

Позвольте мне знать, если есть более простой способ сделать это о.

+0

Стоит отметить, что если строка содержит символы, которые не могут быть представлены в ASCII, после преобразования не будет той же строки. Возможно, эти символы отсутствуют, или это может исказиться, в зависимости от того, как работает Encoding.Convert (чего я не знаю). –

+0

На самом деле я просто протестировал некоторые сценарии, и то, что вы говорите, верно. Вы знаете, как преодолеть это ограничение. Например, если у меня есть один из специальных апострофов, чтобы заменить его на общий. – Geo

7

Для тех, кто любит методы расширения, этот делает трюк для нас.

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

(система имена, так это доступно в значительной степени автоматически для всех наших строк.)

5

На основании ответа Марка выше (и Geo Замечание), я создал версию два лайнера, чтобы удалить все случаи ASCII исключений из строки. Предоставляется людям, которые ищут этот ответ (как и я).

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

Если вы хотите 8-разрядное представление символов, используемых во многих кодировках, это может вам помочь.

Вы должны изменить переменную targetEncoding на любую кодировку, которую вы хотите.

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