File.Copy и кодировка символов - PullRequest
0 голосов
/ 16 июня 2009

Я заметил странное поведение File.Copy() в .NET 3.5SP1. Я не знаю, это ошибка или особенность. Но я знаю, что это сводит меня с ума. Мы используем File.Copy() в пользовательском шаге сборки, и это портит кодировку символов.

Когда я копирую текстовый файл в кодировке ASCII поверх текстового файла в кодировке UTF-8, целевой файл все еще имеет кодировку UTF-8, но содержит содержимое нового файла плюс 3 префиксных символа для UTF-8. Это хорошо для символов ASCII, но неверно для остальных символов (128-255) кодовой страницы ANSI.

Вот код для воспроизведения. Сначала я копирую файл UTF-8 в место назначения, затем копирую файл ANSI в то же место. Обратите внимание на вывод второго вывода консоли: Content of copy.txt : this is ASCII encoded: / Encoding: utf-8

File.WriteAllText("ANSI.txt", "this is ANSI encoded: é", Encoding.GetEncoding(0));
File.WriteAllText("UTF8.txt", "this is UTF8 encoded: é", Encoding.UTF8);

File.Copy("UTF8.txt", "copy.txt", true);

using (StreamReader reader = new StreamReader("copy.txt", true))
{
    Console.WriteLine("Content of copy.txt : " + reader.ReadToEnd() + " / Encoding: " +
                reader.CurrentEncoding.BodyName);
}

File.Copy("ANSI.txt", "copy.txt", true);

using (StreamReader reader = new StreamReader("copy.txt", true))
{
    Console.WriteLine("Content of copy.txt : " + reader.ReadToEnd() + " / Encoding: " + 
                reader.CurrentEncoding.BodyName);
}

Есть идеи, почему это происходит? Есть ли ошибка в моем коде? Любые идеи, как это исправить (моя текущая идея состоит в том, чтобы удалить файл раньше, если он существует)

РЕДАКТИРОВАТЬ: исправить путаницу ANSI / ASCII

Ответы [ 2 ]

1 голос
/ 16 июня 2009

Где вы пишете ASCII.txt? Вы пишете ANSI.txt в первой строке, но это, конечно, не ASCII, поскольку ASCII не содержит символов с акцентом. Файл ANSI не содержит преамбулы, указывающей, что это ANSI, а не ASCII или UTF-8.

Похоже, вы, по сути, передумали между ASCII и ANSI, наполовину написав пример.

Я ожидал бы, что любой файл ASCII будет «обнаружен» как UTF-8, но обнаружение кодирования основывается на том, что файл имеет метку порядка байтов, что-то отличное от UTF-8. Это не значит, что он читает весь файл, а затем догадывается, что такое кодировка.

Из документов для StreamReader:

Этот конструктор инициализирует кодирование в UTF8Encoding, Свойство BaseStream с использованием потока параметр и внутренний буфер размер по умолчанию.

DetectionEncodingFromByteOrderMarks параметр определяет кодировку глядя на первые три байта поток. Это автоматически распознает UTF-8, little-endian Unicode и текст с прямым порядком байтов Unicode если файл начинается с соответствующие метки порядка байтов. Увидеть Метод Encoding.GetPreamble для более информация.

Теперь File.Copy просто копирует необработанные байты с места на место - он не должен изменять что-либо с точки зрения кодировки символов, потому что он не пытается интерпретировать файл как текстовый файл во-первых.

Мне не совсем понятно, где вы видите проблему (частично из-за части ANSI / ASCII). Я предлагаю вам выделить вопросы "File.Copy меняет вещи?" и "какая кодировка символов обнаружена StreamReader?" и в вашем уме, и в вашем вопросе. Ответы должны быть:

  • File.Copy не должен изменять содержимое файла вообще
  • StreamReader может обнаруживать только UTF-8 и UTF-16; если вам нужно прочитать файл, закодированный в любой другой кодировке, вы должны указать это явно в конструкторе. (Кстати, я бы лично порекомендовал использовать Encoding.Default вместо Encoding.GetEncoding(0). Думаю, это понятнее.)
0 голосов
/ 16 июня 2009

Я сомневаюсь, что это как-то связано с File.Copy. Я думаю, что вы видите, что StreamReader использует UTF-8 по умолчанию для декодирования, и, поскольку UTF-8 обратно совместим, StreamReader никогда не имеет причин прекращать использование UTF-8 для чтения ANSI-кодированного файла.

Если вы откроете ASCII.txt и copy.txt в шестнадцатеричном редакторе, они идентичны?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...