Чтение файла Unicode в C и передача содержимого в виде ASCII через сокеты - PullRequest
2 голосов
/ 05 июня 2009

Я пытаюсь понять это, но, похоже, ничего не работает. У нас есть приложение он читает тысячи файлов транзакций, используя обычные "fopen fgets и т. д.", которые мы анализируем с помощью обычных функций C "strstr, strchr и т. д." и возвращаем обратно нормализованный символ *.

Однако теперь нам нужно прочитать некоторые файлы в Unicode (из Windows), и у меня много проблем. Из того, над чем я работаю, я получаю только FP (указатель файла), не зная, указывает ли FP на обычный файл ascii или Unicode, и мне нужно отправить обратно в приложение как char *.

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

Я пытался использовать WideCharToMultiByte, mbsrtowcs, но кажется, что после того, как я прочитал файл, используя fgets, и передал им, возвращаемое значение всегда пустое (0 байт). У кого-нибудь есть пример, как это сделать правильно? В онлайновых документах / руководствах по этим функциям отсутствуют хорошие примеры.

Спасибо!

Ответы [ 3 ]

4 голосов
/ 05 июня 2009

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

В Windows обычно используют метку порядка байтов в начале файла, но это нарушает многие практики и ломает многие вещи - так что это не распространено в мире Unix.

Есть куча библиотек, предназначенных только для этого - кодировки Unicode и символов. Наиболее популярными являются iconv и ICU .

4 голосов
/ 05 июня 2009

У меня нет полного ответа, но часть проблемы заключается в определении кодировки символов. Обычно файлы формата Unicode, созданные в Windows, начинаются с метки порядка байтов (BOM) - символа Unicode U + FEFF. Это можно использовать для определения кодировки, если она найдена.

Если у вас есть строка, закодированная с помощью, скажем, UTF16, она будет иметь любое количество встроенных байтов NULL, вы не можете использовать обычные версии ASCII строковых функций (strlen и т. Д.), Так как они будут видеть байты NULL в качестве маркер конца строки. Ваша стандартная библиотека будет иметь версии с поддержкой юникода, которые вы должны использовать.

1 голос
/ 05 июня 2009

Несколько баллов:

Если вы можете быть уверены, что файлы UNICODE имеют метку порядка байтов (BOM), вы можете посмотреть на это. Однако для файлов UNICODE не требуется , чтобы иметь спецификацию, поэтому это зависит от того, откуда они берутся.

Если файл имеет значение UNICODE, вы не можете прочитать его с помощью функции fgets (), вам нужно использовать fgetws () или fread (). Символы UNICODE могут иметь ноль байтов (байтов со значением ноль), что приведет к путанице в fgets ().

Нулевые байты могут быть вашими друзьями. Если вы прочитали комок файла с помощью fread () и обнаружили встроенные нулевые байты, скорее всего, у вас есть UNICODE. Однако обратное неверно - отсутствие нулевых байтов не доказывает, что у вас есть ASCII. Английские буквы в UNICODE будут иметь нулевые байты, но многие другие языки (например, китайский) не будут.

Если вы знаете, на каком языке написан текст, вы можете проверить наличие символов, которые недопустимы на этом языке, но это не так.

Выше я использую UNICODE для Windows - для обозначения UTF16 с порядком байтов Intel. Однако в реальном мире вы можете получить UTF8 или UTF32, и вы можете получить порядок байтов не от Intel. (Теоретически вы можете получить UTF7, но это довольно редко).

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

В противном случае, если вы знаете язык файлов, вы можете попытаться угадать кодировку, но это менее чем на 100% надежно. В противном случае вам может потребоваться указать оператору (если он есть) указать кодировку.

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