Нужна помощь в понимании кодировки UTF - PullRequest
2 голосов
/ 11 июня 2011

Привет, я заметил, что когда я сохраняю текстовый файл, используя кодировку UTF-8 (без спецификации), я могу прекрасно его прочитать, используя кодировку UTF-16 на C #. Теперь это немного смутило меня, потому что UTF-8 использует только 8 бит, верно? И utf-16 занимает, ну, 16 бит для каждого символа.

Теперь представьте, что у меня есть строка "ab", записанная в этом файле как UTF-8, тогда есть один байт для буквы "a" и еще один для "b".

Хорошо, но как можно прочитать этот файл UTF-8 при использовании кодировки UTF-16? На мой взгляд, при чтении файла два байта "ab" будут ошибочно приняты за один символ, содержащий оба байта. Потому что UTF-16 нужны эти 2 байта.

Вот как я это читаю (t.txt кодируется как UTF-8):

using(StreamReader sr = new StreamReader(File.OpenRead("t.txt"), Encoding.GetEncoding("utf-16")))
{
    Console.Write(sr.ReadToEnd());
    Console.ReadKey();
}

Ответы [ 3 ]

5 голосов
/ 11 июня 2011

Проверьте http://www.joelonsoftware.com/articles/Unicode.html, ответит на все ваши вопросы по Unicode

1 голос
/ 11 июня 2011

взгляните на следующую статью:

http://www.joelonsoftware.com/printerFriendly/articles/Unicode.html

1 голос
/ 11 июня 2011

The '8' means it uses 8-bit blocks to represent a character. Это не означает, что каждый символ занимает фиксированные 8 бит.Количество блоков на символ варьируется от 1 до 4 (хотя теоретически длина символов может достигать 6 байтов).

Попробуйте этот простой тест,

  • Создайте текстовый файл (скажем,Блокнот ++) с UTF8 без кодировки BOM
  • Считайте текстовый файл (как вы сделали в своем коде) с помощью File.ReadAllBytes().byte[] utf8 = File.ReadAllBytes(@"E:\SavedUTF8.txt");
  • Проверьте количество байтов, взятых каждым символом.
  • Теперь попробуйте то же самое с файлом, закодированным как ANSI byte[] ansi = File.ReadAllBytes(@"E:\SavedANSI.txt");
  • Сравните байты на символдля обеих кодировок.

Примечание. File.ReadAllBytes () пытается автоматически определить кодировку файла на основе наличия меток порядка байтов.Можно определить форматы кодирования UTF-8 и UTF-32 (как с прямым порядком байтов, так и с прямым порядком байтов).


Интересные результаты
SavedUTF8.txt содержит символ

  • a: количество байтов в байтовом массиве = 1 1 byte per character
  • © (UTF + 00A9) (Alt + 0169): количество байтов в байтовом массиве= 2 2 bytes per character
  • : (UTF + E0A080) (Alt + 14721152) Количество байтов в байтовом массиве = 3 3 bytes per character

ANSI кодировкавсегда занимает 8 бит (т. е. в приведенном выше примере массив байтов всегда будет иметь размер 1 независимо от символа в файле).Как указывает @tchrist, UTF16 использует 2 или 4 байта на символ (а не фиксированные 2 байта на символ).


Таблица кодирования (из здесь )
Следующие последовательности байтов используются для представления символа.Используемая последовательность зависит от номера Unicode символа:

U-00000000 – U-0000007F:    0xxxxxxx
U-00000080 – U-000007FF:    110xxxxx 10xxxxxx
U-00000800 – U-0000FFFF:    1110xxxx 10xxxxxx 10xxxxxx
U-00010000 – U-001FFFFF:    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 – U-03FFFFFF:    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 – U-7FFFFFFF:    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

Битовые позиции xxx заполняются битами кодового номера символа в двоичном представлении.Самый правый бит x является младшим битом.Может использоваться только кратчайшая возможная многобайтовая последовательность, которая может представлять кодовый номер символа.Обратите внимание, что в многобайтовых последовательностях число первых 1 битов в первом байте идентично количеству байтов во всей последовательности.


Определение размера символа

Первый байт многобайтовой последовательности, которая представляет не-ASCII-символ, всегда находится вдиапазон от 0xC0 до 0xFD, и это указывает, сколько байтов следует за этим символом.

Это означает, что старшие биты для 2-байтового символа (110) отличаются от старших битов для 3-байтового символа (1110).Эти начальные биты могут использоваться для уникальной идентификации количества байтов, которые занимает символ.


Дополнительная информация

...