Использование .NET как преобразовать текстовые файлы в кодировке ISO 8859-1, содержащие символы с диакритическими знаками Latin-1, в UTF-8

Мне отправляют текстовые файлы, сохраненные в формате ISO 88591-1, которые содержат символы с диакритическими знаками. из диапазона Latin-1 (а также обычного ASCII az и т. д.). Как преобразовать эти файлы в UTF-8 с помощью C #, чтобы символы в ISO 8859-1 становятся действительными символами UTF-8?

Я попытался использовать StreamReader с кодировкой ASCIIEncoding, а затем преобразовал строку ASCII в UTF-8, создав экземпляры кодировки ascii и кодировки utf8, а затем используя Encoding.Convert(ascii, utf8, ascii.GetBytes( asciiString) ), но символы с диакритическими знаками отображаются как вопросительные знаки.

Какой шаг мне не хватает?


person Tim    schedule 07.04.2010    source источник
comment
Вы пробовали использовать StreamWriter с кодировкой UTF8 для записи asciiString в текстовый файл? Это делает это?   -  person Task    schedule 07.04.2010
comment
@Task: его проблема в том, что он никогда не получает строку из 8859-1, а не в том, что он не может сохранить ее в UTF-8.   -  person Adam Robinson    schedule 08.04.2010
comment
О, это полностью его проблема, без вопросов. Мне просто легче отлаживать преобразование текста с помощью пары StreamReader / StreamWriter (чтобы я мог видеть входящие / исходящие файлы), а не с помощью вызова Encoding.Convert. Это может быть только я.   -  person Task    schedule 08.04.2010
comment
@Task: согласен (отсюда и мой ответ!);)   -  person Adam Robinson    schedule 08.04.2010


Ответы (2)


Вам нужно получить правильный объект Encoding. ASCII имеет такое же название: ASCII, что означает, что он поддерживает только 7-битные символы ASCII. Если вы хотите преобразовать файлы, это, вероятно, проще, чем иметь дело с байтовыми массивами напрямую.

using (System.IO.StreamReader reader = new System.IO.StreamReader(fileName,
                                       Encoding.GetEncoding("iso-8859-1")))
{
    using (System.IO.StreamWriter writer = new System.IO.StreamWriter(
                                           outFileName, Encoding.UTF8))
    {
        writer.Write(reader.ReadToEnd());
    }
}

Однако, если вы хотите сами иметь байтовые массивы, это достаточно просто сделать с помощью Encoding.Convert.

byte[] converted = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), 
    Encoding.UTF8, data);

Однако здесь важно отметить, что если вы хотите пойти по этому пути, вам не следует не использовать для ввода-вывода вашего файла программы чтения строк на основе кодирования, такие как StreamReader. FileStream подойдет лучше, так как он будет читать фактические байты файлов.

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

using (System.IO.FileStream input = new System.IO.FileStream(fileName,
                                    System.IO.FileMode.Open, 
                                    System.IO.FileAccess.Read))
{
    byte[] buffer = new byte[input.Length];

    int readLength = 0;

    while (readLength < buffer.Length) 
        readLength += input.Read(buffer, readLength, buffer.Length - readLength);

    byte[] converted = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), 
                       Encoding.UTF8, buffer);

    using (System.IO.FileStream output = new System.IO.FileStream(outFileName,
                                         System.IO.FileMode.Create, 
                                         System.IO.FileAccess.Write))
    {
        output.Write(converted, 0, converted.Length);
    }
}

В этом примере переменная buffer заполняется фактическими данными в файле как byte[], поэтому преобразование не выполняется. Encoding.Convert задает кодировку источника и назначения, а затем сохраняет преобразованные байты в переменной с именем ..._ 11_. Затем это напрямую записывается в выходной файл.

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

person Adam Robinson    schedule 07.04.2010
comment
спасибо всем за помощь и особенно @Adam за подробный ответ - person Tim; 22.04.2010

Если файлы относительно небольшие (скажем, ~ 10 мегабайт), вам понадобится всего две строки кода:

  string txt = System.IO.File.ReadAllText(inpPath, Encoding.GetEncoding("iso-8859-1"));
  System.IO.File.WriteAllText(outPath, txt);
person Hans Passant    schedule 07.04.2010
comment
Почему ваше решение работает только тогда, когда читаемый файл меньше 10 мегабайт? - person bit; 27.07.2020