Как именно программа конвертирует все в UTF-8 внутри? - PullRequest
3 голосов
/ 07 мая 2010
  • использует ли она setlocale ()?
  • предполагает ли utf-8 для всех входных строк в локали UTF-8?
  • Я понимаю, что такое юникод и как он связан с utf-8, но как внутренне "преобразовать в него" все их строки?

Как он преобразует все входные строки в UTF-8? Использует ли он функцию библиотеки C?

Должен ли текущий рабочий язык быть языком UTF-8?

ОБНОВЛЕНИЕ : если бы в вашем ответе были конкретные технические детали, это было бы здорово, поскольку это больше соответствует тому, что я ищу. Я уже понимаю причины внутреннего использования UTF-8 и почему он упрощает работу с несколькими локалями.

ОБНОВЛЕНИЕ : ответ, упомянутый просто для использования iconv и / или ICU, однако, как strcmp() вместе со всеми другими подпрограммами узнает, что сравнивать их как UTF-8? setlocale() должен быть запущен? Или это не имеет значения?

Ответы [ 5 ]

5 голосов
/ 07 мая 2010

Трудно сказать, с чего начать, поскольку в игре много предположений.

В C, как мы его знаем и любим, есть тип данных 'char'. Во всех широко используемых реализациях этот тип данных содержит 8-битный байт.

В языке, в отличие от любых библиотечных функций, которые вы используете, эти вещи являются просто целыми числами, дополняющими два. У них нет семантики «характера».

Как только вы начинаете вызывать функции из стандартной библиотеки с именами 'str' или 'is' (например, strcmp, isalnum), вы имеете дело с семантикой символов.

Программы на C должны были справиться с гигантским беспорядком, состоящим из семантики символов, до изобретения Unicode. Различные организации изобрели очень большое количество стандартов кодирования. Некоторые из них по одному символу на байт. Некоторые из них являются несколькими символами на байт. В некоторых всегда можно спросить if (charvalue == 'a'). В других случаях это может привести к неправильному ответу из-за многобайтовой последовательности.

Почти в каждой современной среде семантика стандартной библиотеки определяется настройкой локали.

Откуда приходит UTF-8? Некоторое время назад был создан консорциум Unicode, чтобы попытаться навести порядок во всем этом хаосе. Unicode определяет символьное значение (в 32-битном символьном пространстве) для многих, многих, многих символов. Цель состоит в том, чтобы охватить все символы практического использования.

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

Концептуально, самый простой способ сделать это - использовать 32-битные символы (UTF-32), и, таким образом, у вас будет один элемент на логический символ. Большинство людей решили, что это нецелесообразно. Обратите внимание, что в современных версиях gcc тип данных wchar_t является 32-разрядным символом, но Microsoft Visual Studio не соглашается, определяя этот тип данных как 16-разрядные значения (UTF-16 или UCS-2, в зависимости от ваша точка зрения).

Большинство не-Windows C программ слишком сильно вложены в 8-битные символы, чтобы их можно было изменить. Итак, стандарт Unicode включает в себя UTF-8, представление текста Unicode в виде последовательности 8-битных байтов. В UTF-8 каждый логический символ имеет длину от 1 до 4 байтов. Основные символы ISO-646 («ascii») «играют сами», поэтому простые операции над простыми символами работают, как и ожидалось.

Если ваша среда включает локали для UTF-8, тогда вы можете установить локаль на локаль UTF-8, и все стандартные функции lib будут просто работать. Если ваша среда не включает локали для UTF-8, вам понадобится дополнение, например ICU или ICONV.

До сих пор все это обсуждение касалось данных, хранящихся в переменных в памяти. Вы также должны иметь дело с чтением и написанием этого. Если вы назовете open(2) или моральный эквивалент Windows, вы получите необработанные байты из файла. Если их нет в UTF-8, вам придется конвертировать их, если вы хотите работать в UTF-8.

Если вы позвоните fopen(3), тогда стандартная библиотека может попытаться оказать вам услугу и выполнить преобразование между ее идеей кодировки файлов по умолчанию и ее идеей о том, что вы хотите в памяти. Если вам нужно, например, запустить программу в системе в греческом языке и прочитать файл на китайском языке в Big5, вам нужно быть осторожным с параметрами, которые вы передаете fopen, или вы, возможно, захотите избегай это. И вам понадобится ICONV или ICU для конвертации в UTF-8 и обратно.

Ваш вопрос упоминает «входные строки». Это может быть несколько вещей. В локали UTF-8 argv будет UTF-8. Файловым дескриптором 0 будет UTF-8. Если оболочка не работает в локали UTF-8, и вы вызываете setlocale для локали UTF-8, вы не обязательно получите значения в UTF-8 в argv. Если вы подключите содержимое файла к дескриптору файла, вы получите все, что находится в файле, в любой кодировке, в которой оно находится.

2 голосов
/ 07 мая 2010

Э-э ... Полагаю, вы спрашиваете о таких вещах, как libiconv или ICU , но ... они просто библиотеки для преобразования наборов символов ...

EDIT:

Вы не можете использовать стандартные функции обработки строк Си, поскольку вы не имеете дело со стандартными строками Си. Версии с поддержкой UTF-8 доступны в таких библиотеках, как glib или ICU .

1 голос
/ 10 мая 2010

ICU использует utf-16 для внутреннего использования (это хороший формат для внутренней работы), но имеет удобные процедуры для сравнения utf-8.Вы сообщаете ему, какой языковой стандарт вы хотите использовать для сравнения, или он может использовать необязательный UCA , если указываете языковой стандарт «root».

1 голос
/ 07 мая 2010

Строка действительно абстрактное понятие. Но внутри компьютера любая строка будет иметь конкретное представление в виде количества байтов с использованием определенной кодировки символов.

Таким образом, «преобразование всего во внутренний UTF-8» означает, что приложение использует UTF-8 для всех внутренних строк, имеет всю свою логику, написанную для работы со строками UTF-8, и преобразует каждый внешний ввод из любой кодировки, которую использует эта строка до UTF-8. Он может или не может позволить вам выбрать, какую кодировку использовать для вывода.

Это действительно самый разумный способ написать приложение, способное обрабатывать текст в разных кодировках, по крайней мере, если внутренняя логика может эффективно работать в UTF-8 (т. Е. Не требует произвольного доступа).

0 голосов
/ 07 мая 2010

Если вы хотите сравнить две строки в C, они должны быть в одной и той же кодировке.strcmp () - это просто memcmp () (или байтовое сравнение), который останавливается на значении 0. В strcmp Си не будет никакого преобразования.Если вам приходится иметь дело с разными кодировками (CP850, UTF-8, Ansi, Windows, Mac), вы должны быть очень осторожны с тем, что вы сравниваете, иначе вы сравниваете яблоки с грушами.

Библиотеки, упомянутые выше, имеютдругая реализация strcmp (), которая знает и обрабатывает кодировку, хотя вы всегда должны знать и предоставлять кодировку самостоятельно.

если вы имеете дело с XML, вы можете использовать libxml, который кодирует для вас вправильное (внутреннее) представление, в зависимости от заданной кодировки через xml-заголовок.

таблицы кодирования / символов - одна из худших концепций в C, начиная с прежних дней, когда символьные байты были длиной 7 бити компьютерный мир состоялся только в США.(чтобы не было умлаутов, акцентов, знака евро и т. д.)

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