LINUX.ORG.RU

Чтение текста, кодировки, wchar_t


0

0

Есть не-ascii текстовый файл. Нужно читать его и обрабатывать посимвольно (пусть, скажем, на каждый символ нужно вызвать iswalnum).

Вопрос следующий: как это вообще правильно делать?

Для начала, как определить кодировку файла? Автоматически определять не хочу, ибо это ненадежно и непредсказуемо. По текущей локали? Флаг коммандной строки для указания кодировки? Есть какая-нибудь принятая схема для CLI утилит для обработки текста? Хотя бы примеров дайте.

Второе: как собственно, читать посимвольно? Ну т.е. желательно читать кусками в буффер, а как потому извлекать оттуда по одному wchar_t? iconv - что-то вроде, но она работает с буфферами целиком, не побуквенно, и с байтами, а не wchar.

anonymous

Определять по текущей локали. Читать по байту, и когда байт завершает символ, обрабатывать его.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Определять по текущей локали. Гуд

> Читать по байту, и когда байт завершает символ, обрабатывать его. Вообще, конечно, логично. С 8бит кодировками проблем вообще нет, с UTF8 начало следующего символа определить тоже легко, соответственно, и конец предыдущего, а другие многобайтовые кодировки, как я понимаю, никому особо и не нужны.

Хорошо, а как получить wchar_t - то? Какого он вообще размера и что там внутри? sizeof(wchar_t) говорит 32, значит UTF32? Под windows ЕМНИП 16бит, не?

Кстати, язык C++, если можно подойдут встроенные средства (iostream, locale), ткните в пример кода плиз.

anonymous
()
Ответ на: комментарий от sergej

Читать по 1 байу за сисколл я не собираюсь. Читаем в буффер или из c++ потока (там кажись есть своя буфферизация). Вопрос - как использовать iconv если в конце буффера может быть часть символа, продолжение которого не влезло, и как получить из массива char, возвращенного iconv'ом, массив wchar_t? Тупо сдвигами и & в зависимости от endianess? wchar_t, кстати, гарантированно 4 байта?

Все-таки меня сильно интересуют встроенные в C/C++ функции работы с локалями. Не просто же так в C есть wcs* функции а в C++ locale, должен быть стандартный способ конвертации в/из этого wchar_t (который предназначен по сути только для использования внутри программы) из/в более стандартные (для хранения и передачи) представления как-то 8битные кодировки и utf8.

anonymous
()
Ответ на: комментарий от anonymous

функция iconv(3) возвращает кол-во успешно перекодированных байт. то что не получилось - оставляешь на след раз.

iconv как раз из массива char с текстом в указанной кодировке сделает тебе массив wchar_t.

Есть подозрение, что существуют системы (виндовс?) в которых sizeof(wchar_t) == 2.

кроме libiconv есть еще mbstowcs(3).

sergej ★★★★★
()
Ответ на: комментарий от sergej

PS - iconv входит в состав glibc с версии 2.1, так что не думаю, что есть большая разница какой из этих функций пользоваться, но iconv у можно указать кодировку явно.

sergej ★★★★★
()
Ответ на: комментарий от sergej

> функция iconv(3) возвращает кол-во успешно перекодированных байт. то что не получилось - оставляешь на след раз

ну в принцыпе да

> iconv как раз из массива char с текстом в указанной кодировке сделает тебе массив wchar_t

откуда вы это взяли?

extern size_t iconv (iconv_t __cd, char **__restrict __inbuf,
             size_t *__restrict __inbytesleft,
             char **__restrict __outbuf,
             size_t *__restrict __outbytesleft);

нет там в помине никаких wchar_t, только в коллбеках для нераскодированных символов.

> кроме libiconv есть еще mbstowcs(3).

multibyte, я так понимаю, utf8? а для 8 bit?

> PS - iconv входит в состав glibc с версии 2.1

это только в Linux.

anonymous
()
Ответ на: комментарий от sergej

> Есть подозрение, что существуют системы (виндовс?) в которых sizeof(wchar_t) == 2.

во-во. А что там? utf-16? В utf-16 бывают символы из 2 и 3 пар байт..

anonymous
()
Ответ на: комментарий от sergej

> multibyte - это в кодировке LC_CTYPE
Примерно разобрался.

setlocale(LC_CTYPE, "") и mbtowc конвертит в wchar_t и из 8bit, и из utf-8 при правильной установке локали.

Только одна загвоздка - если из utf8 получатеся wchar_t с корректным utf-32 значением, из 8битных кодировок получаются wchar_t с теми же самыми 8 битами. Это нехорошо. Но вообще mbtowc делает именно то, что мне нужно и работает посимвольно.

> char * в иконве можно привести к wchar_t*. ей пофиг.

ну да. И огрести проблем в зависимости от endianess, размера и реального содержимого wchar_t.

anonymous
()
Ответ на: комментарий от anonymous

>> И огрести проблем в зависимости от endianess, размера и реального содержимого wchar_t.

ниче подобного - он все сделает правильно, если конечно ты не укажешь UCS4LE на bigendian машине и наоборот.

про теже самые 8 бит - не понял.

sergej ★★★★★
()
Ответ на: комментарий от sergej

> про теже самые 8 бит - не понял.

на входе 8битная koi8r, на выходе в wchar_t то же самое значение, что было во входном байте вместо ожидаемого UTF32

anonymous
()
Ответ на: комментарий от anonymous

странно. ну ascii понятно совпадает с юникодом, а русские буквы он должен был поменять. мож с локалью что...

sergej ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.