Использование .NET, как преобразовать текстовые файлы в кодировке ISO 8859-1, содержащие символы латинского алфавита-1, в UTF-8 - PullRequest
16 голосов
/ 07 апреля 2010

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

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

Какой шаг я пропускаю?

Ответы [ 2 ]

34 голосов
/ 07 апреля 2010

Вам нужно получить правильный 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 указывает кодировку источника и назначения, затем сохраняет преобразованные байты в переменной с именем ... converted. Затем он записывается непосредственно в выходной файл.

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

13 голосов
/ 08 апреля 2010

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

  string txt = System.IO.File.ReadAllText(inpPath, Encoding.GetEncoding("iso-8859-1"));
  System.IO.File.WriteAllText(outPath, txt);
...