Как преобразовать (транслитерировать) строку из utf8 в ASCII (один байт) в С#?

У меня есть строковый объект

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

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

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

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

РЕДАКТИРОВАТЬ 1: Мы пытаемся избавиться от специальных символов, таких как некоторые специальные апострофы окон. Код, который я разместил ниже в качестве ответа, не позаботится об этом. В основном

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


person Geo    schedule 31.01.2009    source источник
comment
Обратите внимание: если вы хотите заменить символы с диакритическими знаками их эквивалентами без диакритических знаков, вы можете использовать str.Normalize(NormalizationForm.FormKD)   -  person yoyo    schedule 30.08.2015


Ответы (5)


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

Похоже на классическую проблему преобразования Unicode в ASCII. Хитрость заключается в том, чтобы найти где это происходит.

.NET отлично работает с Unicode, если предположить, что ему сказали, что это Unicode для начала (или оставить по умолчанию).

Я предполагаю, что принимающее приложение не может с этим справиться. Итак, я бы, вероятно, использовал ASCIIEncoder с EncoderReplacementFallback со строкой.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));

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

person Mark Brackett    schedule 31.01.2009
comment
Спасибо, это сработало отлично. Мне просто нужно было внести небольшое изменение. Кодировщик кодирования = ASCIIEncoding.GetEncoding (us-ascii, новый EncoderReplacementFallback (string.Empty), новый DecoderExceptionFallback ()); - person Geo; 31.01.2009
comment
+1 за EncoderReplacementFallback - я никогда раньше об этом не слышал. Любить это. - person Dan Esparza; 01.11.2012
comment
EncoderReplacementFallback со знаком вопроса используется по умолчанию. В этом случае кажется, что желательно лучше с потерями. Резервный вариант исключения полезен, когда потери недопустимы (что, ИМХО, должно быть по умолчанию). - person Tom Blodget; 17.07.2016

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

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

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

person Geo    schedule 31.01.2009
comment
Стоит отметить, что если строка содержит символы, которые не могут быть представлены в ASCII, после преобразования она не будет той же самой строкой. Эти символы могут отсутствовать или они могут быть искажены, в зависимости от того, как работает Encoding.Convert (чего я не знаю). - person David Z; 31.01.2009
comment
На самом деле я только что проверил несколько сценариев, и то, что вы говорите, верно. Вы знаете, как преодолеть это ограничение. Например, если у меня есть один из специальных апострофов, чтобы заменить его обычным. - person Geo; 31.01.2009

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

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

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

person Peter Drier    schedule 02.02.2012

Основываясь на ответе Марка выше (и комментарии Гео), я создал двухстрочную версию, чтобы удалить все случаи исключения 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)); 
person tonycoupland    schedule 28.03.2014

Если вам нужно 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);
person Rapeapach Suwasri    schedule 17.07.2016