Замена символов в С# (ascii)

У меня есть файл с такими символами: à, è, ì, ò, ù - À. Мне нужно заменить эти символы обычными символами, например: à = a, è = e и т.д. Это мой код:

StreamWriter sw = new StreamWriter(@"C:/JoinerOutput.csv");
string path = @"C:/Joiner.csv";
string line = File.ReadAllText(path);

if (line.Contains("à"))
{
    string asAscii = Encoding.ASCII.GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(Encoding.ASCII.EncodingName, new EncoderReplacementFallback("a"), new DecoderExceptionFallback()), Encoding.UTF8.GetBytes(line)));
    Console.WriteLine(asAscii);
    Console.ReadLine();

    sw.WriteLine(asAscii);
    sw.Flush();
}

В основном это ищет файл для определенного символа и заменяет его другим. Проблема, с которой я столкнулся, заключается в том, что моя инструкция if не работает. Как мне решить это?

Это образец входного файла:

Dimàkàtso Mokgàlo
Màmà Ràtlàdi
Koos Nèl
Pàsèkà Modisè
Jèrèmiàh Morèmi
Khèthiwè Buthèlèzi
Tiànà Pillày
Viviàn Màswàngànyè
Thirèshàn Rèddy
Wàdè Cornèlius
ènos Nètshimbupfè

Это результат, если используется: line = line.Replace('à', 'a');

Ch�rl�n� Kirst�n
M�m� R�tl�di
Koos N�l
P�s�k� Modis�
J�r�mi�h Mor�mi
Kh�thiw� Buth�l�zi
Ti�n� Pill�y
Vivi�n M�sw�ng�ny�
Thir�sh�n R�ddy
W�d� Corn�lius
�nos N�tshimbupf�

С моим кодом символ будет полностью удален.

Ответ 1

Не знаю, полезно ли это, но во внутреннем инструменте для написания сообщения на экране водить мы имеем следующие замены (я уверен, что есть более интеллектуальные способы сделать эту работу для таблиц Unicode, но это для этого небольшого внутреннего инструмента достаточно одного):

        strMessage = Regex.Replace(strMessage, "[éèëêð]", "e");
        strMessage = Regex.Replace(strMessage, "[ÉÈËÊ]", "E");
        strMessage = Regex.Replace(strMessage, "[àâä]", "a");
        strMessage = Regex.Replace(strMessage, "[ÀÁÂÃÄÅ]", "A");
        strMessage = Regex.Replace(strMessage, "[àáâãäå]", "a");
        strMessage = Regex.Replace(strMessage, "[ÙÚÛÜ]", "U");
        strMessage = Regex.Replace(strMessage, "[ùúûüµ]", "u");
        strMessage = Regex.Replace(strMessage, "[òóôõöø]", "o");
        strMessage = Regex.Replace(strMessage, "[ÒÓÔÕÖØ]", "O");
        strMessage = Regex.Replace(strMessage, "[ìíîï]", "i");
        strMessage = Regex.Replace(strMessage, "[ÌÍÎÏ]", "I");
        strMessage = Regex.Replace(strMessage, "[š]", "s");
        strMessage = Regex.Replace(strMessage, "[Š]", "S");
        strMessage = Regex.Replace(strMessage, "[ñ]", "n");
        strMessage = Regex.Replace(strMessage, "[Ñ]", "N");
        strMessage = Regex.Replace(strMessage, "[ç]", "c");
        strMessage = Regex.Replace(strMessage, "[Ç]", "C");
        strMessage = Regex.Replace(strMessage, "[ÿ]", "y");
        strMessage = Regex.Replace(strMessage, "[Ÿ]", "Y");
        strMessage = Regex.Replace(strMessage, "[ž]", "z");
        strMessage = Regex.Replace(strMessage, "[Ž]", "Z");
        strMessage = Regex.Replace(strMessage, "[Ð]", "D");
        strMessage = Regex.Replace(strMessage, "[œ]", "oe");
        strMessage = Regex.Replace(strMessage, "[Œ]", "Oe");
        strMessage = Regex.Replace(strMessage, "[«»\u201C\u201D\u201E\u201F\u2033\u2036]", "\"");
        strMessage = Regex.Replace(strMessage, "[\u2026]", "...");

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


Обратите внимание, что правильным решением было бы использовать таблицы Unicode, заменяя символы интегрированными диакритическими знаками на их "комбинированную диакритическую марку (знаки)" + символ, а затем удаляя диакритические знаки...

Ответ 2

Другие прокомментировали использование таблицы поиска Unicode для удаления диакритики. Я сделал быстрый поиск Google и нашел этот пример. Код бесстыдно скопирован (переформатирован) и размещен ниже:

using System;
using System.Text;
using System.Globalization;

public static class Remove
{
    public static string RemoveDiacritics(string stIn)
    {
        string stFormD = stIn.Normalize(NormalizationForm.FormD);
        StringBuilder sb = new StringBuilder();

        for(int ich = 0; ich < stFormD.Length; ich++) {
            UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
            if(uc != UnicodeCategory.NonSpacingMark) {
                sb.Append(stFormD[ich]);
            }
        }

        return(sb.ToString().Normalize(NormalizationForm.FormC));
    }
}

Итак, ваш код может очистить ввод, вызвав:

line = Remove.RemoveDiacritics(line);

Ответ 3

Я часто использую метод extenstion, основанный на версии Dana. Краткое объяснение:

  • Нормализация для формирования D разбивает такие символы, как и на e, а не на пробел `
  • Из этого удаляются символы nospacing.
  • Результат нормализуется до формы D (я не уверен, что это необходимо)

код:

using System.Linq;
using System.Text;
using System.Globalization;

// namespace here
public static class Utility
{
    public static string RemoveDiacritics(this string str)
    {
        if (str == null) return null;
        var chars =
            from c in str.Normalize(NormalizationForm.FormD).ToCharArray()
            let uc = CharUnicodeInfo.GetUnicodeCategory(c)
            where uc != UnicodeCategory.NonSpacingMark
            select c;

        var cleanStr = new string(chars.ToArray()).Normalize(NormalizationForm.FormC);

        return cleanStr;
    }
}

Ответ 4

Почему вы усложняете ситуацию?

line = line.Replace('à', 'a');

Update:

Документы для File.ReadAllText говорят:

Этот метод пытается автоматически определить кодировку файла на основе наличие знаков байтового порядка. Форматы кодирования UTF-8 и UTF-32 (как для большого, так и для малочисленных) могут быть обнаружены.

Используйте ReadAllText (String, Encoding) перегрузка метода при чтении файлов который может содержать импортированный текст, потому что непризнанные символы могут не читайте правильно.

Какая кодировка C:/Joiner.csv в? Может быть, вы должны использовать другую перегрузку для File.ReadAllText, где вы сами указываете входную кодировку?

Ответ 5

Используйте это:

     if (line.Contains("OldChar"))
     {
        line = line.Replace("OldChar", "NewChar");
     }

Ответ 6

Похоже, что вы хотите преобразовать Extended ASCII (восемь бит) в ASCII (семибитный), поэтому поиск может помочь.

Я видел библиотеки, которые могли бы обрабатывать это на других языках, но никогда не приходилось делать это на С#, похоже, что это может быть несколько просветляющим:

Преобразуйте два символа ascii в их "соответствующее" односимвольное расширенное представление ascii

Ответ 7

Делать это легко. Код ниже заменит все специальные символы на символы ASCII всего за 2 строки кода. Это дает вам тот же результат, что и решение Жюльена Ронкалья.

byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(inputText);
string outputText = System.Text.Encoding.ASCII.GetString(bytes);