Обработка специальных символов в C (кодировка UTF-8)
Я пишу небольшое приложение на C, которое читает простой текстовый файл, а затем выводит строки один за другим. Проблема заключается в том, что текстовый файл содержит специальные символы, такие как Æ, Ø и Å. Когда я запускаю программу в терминале, вывод для этих символов представлен "?".
Есть ли легкое исправление?
Ответы
Ответ 1
Прежде всего:
- Чтение в буфере
- Используйте libiconv или аналогичный для получения типа wchar_t из UTF-8 и используйте широкие функции обработки символов, такие как wprintf()
- Используйте широкие функции символов в C! Большинство функций обработки файлов и вывода имеют широкоформатный вариант
Убедитесь, что ваш терминал может работать с выходом UTF-8. Наличие правильной настройки локали и управление данными локали может автоматически автоматизировать процесс открытия и преобразования файлов... в зависимости от того, что вы делаете.
Помните, что ширина кодовой точки или символа в UTF-8 является переменной. Это означает, что вы не можете просто искать байта и начинать читать, как с ASCII... потому что вы можете приземлиться в середине кодовой точки. Хорошие библиотеки могут это сделать в некоторых случаях.
Вот какой-то код (не мой), который демонстрирует некоторое использование чтения файлов UTF-8 и широкую обработку символов в C.
#include <stdio.h>
#include <wchar.h>
int main()
{
FILE *f = fopen("data.txt", "r, ccs=UTF-8");
if (!f)
return 1;
for (wint_t c; (c = fgetwc(f)) != WEOF;)
printf("%04X\n", c);
fclose(f);
return 0;
}
Ссылки
Ответ 2
Убедитесь, что вы случайно не отбрасываете байты; некоторые символы UTF-8 имеют длину более одного байта (эта точка), и вам нужно сохранить их все.
Может быть полезно распечатать содержимое буфера в виде шестнадцатеричного кода, чтобы вы могли проверить, какие байты действительно читаются:
static void print_buffer(const char *buffer, size_t length)
{
size_t i;
for(i = 0; i < length; i++)
printf("%02x ", (unsigned int) buffer[i]);
putchar('\n');
}
Вы можете сделать это после загрузки очень короткого файла, содержащего всего несколько символов.
Также убедитесь, что терминал настроен на правильное кодирование, поэтому он интерпретирует ваши символы как UTF-8.
Ответ 3
Возможно, ваш текстовый файл кодируется ISO-8559-1, но ваш терминал UTF-8. Такое несоответствие является стандартной проблемой при работе с байт-ориентированной обработкой текста; другие C-программы (такие как стандартные команды "cat" и "more" ) будут делать то же самое, и обычно это не считается ошибкой или чем-то, что необходимо устранить.
Если вы хотите работать с символьным уровнем Unicode, а не с байтами, но вам нужно будет использовать wchar в качестве типа вашего персонажа вместо char во всей вашей программе и предоставить ключи для пользователя, чтобы указать, что на самом деле кодирование входящего файла. (Хотя иногда можно угадать, это не очень надежно.)
Ответ 4
Я не знаю, может ли это помочь, но если вы уверены, что кодировки терминального и входного файлов одинаковы, вы можете попробовать setlocale()
:
#include <locale.h>
…
setlocale(LC_CTYPE, "");