Почему .net использует кодировку UTF16 для строки, но использует utf8 по умолчанию для сохранения файлов?

Отсюда

По существу, строка использует форму кодировки символов UTF-16

Но при сохранении vs StreamWriter:

Этот конструктор создает StreamWriter с кодировкой UTF-8 без Значок байтового заказа (BOM),

Я видел этот образец (удаленная ссылка):

enter image description here

И похоже, что utf8 меньше для некоторых строк, а utf-16 меньше в некоторых других строках.

  • Итак, почему .net использует utf16 как кодировку по умолчанию для строки, а utf8 для сохранения файла?

Спасибо.

p.s. Ive уже прочитал знаменитую статью

Ответ 1

Если вы счастливы игнорировать суррогатные пары (или, что то же самое, возможность вашего приложения, нуждающегося в символах вне базовой многоязычной плоскости), UTF-16 обладает некоторыми хорошими свойствами, в основном из-за того, что всегда требуется два байта на единицу кода и представляет все BMP в одном блоке кода.

Рассмотрим примитивный тип char. Если мы используем UTF-8 как представление в памяти и хотим справиться со всеми символами Юникода, насколько это должно быть? Это может быть до 4 байтов... что означает, что нам всегда нужно выделять 4 байта. В этот момент мы могли бы также использовать UTF-32!

Конечно, мы могли бы использовать UTF-32 в качестве представления char, но UTF-8 в представлении string, преобразовывая, когда мы идем.

Два недостатка UTF-16:

  • Количество единиц кода для символа Юникода является переменной, поскольку не все символы находятся в BMP. До тех пор, пока emoji не стал популярным, это не повлияло на многие приложения в повседневном использовании. В наши дни, конечно, для приложений для обмена сообщениями и т.п. Разработчикам, использующим UTF-16, действительно нужно знать о суррогатных парах.
  • Для простого ASCII (который много текста, по крайней мере, на западе) он занимает в два раза больше пространства эквивалентного текста в кодировке UTF-8.

(В качестве побочного примечания я полагаю, что Windows использует UTF-16 для данных Unicode, и для .NET имеет смысл следовать примеру аргументов interop. Это просто задает вопрос на одном шаге.)

Учитывая проблемы суррогатных пар, я подозреваю, что язык/платформа разрабатывались с нуля без требований к взаимодействию (но основываясь на обработке текста в Юникоде), UTF-16 не был бы лучшим выбором. Либо UTF-8 (если вы хотите повысить эффективность памяти и не возражаете против сложности обработки с точки зрения получения до n-го символа), либо UTF-32 (наоборот) будет лучшим выбором. (Даже получение n-го символа имеет "проблемы" из-за таких вещей, как разные формы нормализации. Текст жестко...)

Ответ 2

Как и во многих "почему это выбрали" вопросы, это было определено историей. В 1993 году Windows стала операционной системой Unicode. В то время Unicode по-прежнему имела только кодовое пространство 65535 кодовых точек, называемое в настоящее время UCS. Только в 1996 году Юникод приобрел дополнительные самолеты, чтобы расширить пространство кодирования до миллиона кодовых точек. И суррогатные пары подходят для 16-битной кодировки, тем самым устанавливая стандарт utf-16.

Строки .NET - это utf-16, потому что это отлично подходит для кодирования операционной системы, не требуется преобразование.

История utf-8 более мрачная. Определенно прошлое Windows NT, RFC-3629 датируется ноябрем 1993 года. Чтобы получить ногу, потребовалось некоторое время. Интернет был полезен.

Ответ 3

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

UTF-16 используется для строк в памяти, потому что быстрее для каждого символа разбирается и сопоставляется непосредственно с символьным классом юникода и другими таблицами. Все строковые функции в Windows используют UTF-16 и работают в течение многих лет.