Подтвердить что ты не робот

Обработка специальных символов в C (кодировка UTF-8)

Я пишу небольшое приложение на C, которое читает простой текстовый файл, а затем выводит строки один за другим. Проблема заключается в том, что текстовый файл содержит специальные символы, такие как Æ, Ø и Å. Когда я запускаю программу в терминале, вывод для этих символов представлен "?".

Есть ли легкое исправление?

4b9b3361

Ответ 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, "");