Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Корректная обработка utf8 в *nix


Автор: leneCaress 9.3.2009, 03:22
Добрый вечер.

Только-только начала переползать на C++ в Linux. (Раньше писала на C++ много, но только под win).

Не понятен один вопрос...

Допустим локаль в системе может быть как UTF8, так а что-нибудь однобайтовое (например koi8r).
Каким способом обрабатывать содержимое строк, получаемых из файлов, из stdin и пр.

Под виндой было все просто. было либо массив char, либо wchar_t...
Они были соответственно по 1 или 2 байта...

А как быть под *nix??
Во первых хотелось бы не использовать какие-то библиотеки типа boost (хочу сначала научится без них).
Во вторых - хотелось бы, чтобы программа работала кроме линукса, еще на bsd, а в идеале и в win.
В третьих - хотелось бы хорошей производительности.
В четвертых - удобства ТЕ вполне с удовольствием пользовалась бы чем-то вроде std::string, std::stringw.

У меня закрадывается подозрение, что нужно просто считывать все данные в wchar_t[]...
Но мыслей как это сделать по человечески - нету.

Вообщем - "хочу пример" ©  smile 

P.S. гуглила.   smile 

P.P.S. не уверена, что пишу в нужный раздел   smile 

Автор: SABROG 9.3.2009, 12:44
Книга "Standard C++ Iostreams and Locales"


Автор: azesmcar 9.3.2009, 15:31
Для начала почитайте тут, довольно много информации по этому поводу.
http://forum.vingrad.ru/forum/topic-249965.html

Цитата

Во вторых - хотелось бы, чтобы программа работала кроме линукса, еще на bsd, а в идеале и в win.


если используете АПИ или что-то наподобие пишите макросы
Код

#ifndef WIN32
    //*nix
#else
    //windows
#endif


Код

В четвертых - удобства ТЕ вполне с удовольствием пользовалась бы чем-то вроде std::string, std::stringw.


в STL есть классы
std::string для анси и
std::wstring для юникода

почитайте ссылку которую я прислал, если останутся вопросы - пишите здесь, обсудим

Автор: leneCaress 9.3.2009, 22:57
Цитата(SABROG @  9.3.2009,  12:44 Найти цитируемый пост)
Книга "Standard C++ Iostreams and Locales"


спасибо smile
раньше пользовалась printf для форматирования строк. думаю что теперь перейду на потоки.


Цитата(azesmcar @  9.3.2009,  15:31 Найти цитируемый пост)
Для начала почитайте тут, довольно много информации по этому поводу.
http://forum.vingrad.ru/forum/topic-249965.html


спасибо!
в принципе с помощью Вашего lexical_cast, думаю, что решу все без проблем =)


Цитата(azesmcar @  9.3.2009,  15:31 Найти цитируемый пост)
если используете АПИ или что-то наподобие пишите макросы


это я вкурсе =)
хотя меня во времена далекой забытой молодости учили локализовывать весь платформо-зависимый код в отдельные модули, а линковать только с необходимым для данной платформы... всеравно периодически #ifdef проскакиевает =)

Цитата(azesmcar @  9.3.2009,  15:31 Найти цитируемый пост)
почитайте ссылку которую я прислал, если останутся вопросы - пишите здесь, обсудим 


хотелось бы услышать авторитетное мнение...

сейчас задача формулируется примерно так: есть большой(>500Mb) объем текстовых данных, висящих у меня в памяти (строки в однобайтовой кодировке или в utf8, кодировка конткретного файла известна), по определенным критериям я его обрабатываю (здесь я обращаю внимания только на цифры, спецсимволы(скобки, кавычки, \t, \n, пробелы) ТЕ кодировка не важна), потом из этого объема я получаю строки(const char*. они содержат символы национальных алфавитов(для меня важны только русский, английский, но возможно в будующем потребуется еще что-то, а-ля китайский)), (это все уже сделано), и вот эти строки мне нужно обработать...
например, самое простое, взять только первые 5 символов и перевести их в верхний регистр...

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

я вижу для себя такое решение задачи...
данных слишком много, чтобы все их перекодировать.
поэтому перекодировать нужно только на тот момент, когда происходит обработка...
мне это представляется вот так:
const char* в cp1251/koi8-r/utf8  ->  буфер с wchar_t  ->  const char* в utf8

для std::string с utf-8 -> std::wstring -> std::string с utf-8 можно использовать ваш код.. (кстати, не совсем поняла, он для сколькибайтного wchar_t?)
а для преобразования cp1251/koi8-r  ->  utf8 привлечь iconv...
это нормальный способ (ТЕ не через (__|__) )?

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


огромное спасибо за помощь!!!


P.S. не пинайте: большой текстовый файл - не моя придумка, а чтобы его обработать нужно произвольно бегать по строкам. эксперементально - самый быстрый способ - загрузить(думаю потом заменить на мапинг, кстати, стоит ли?) его весь в память и уже в памяти мучать.

P.P.S. под никсами раньше писала только на Java, Python...
в них проблема с кодировками как-то решена и никогда даже не всплывала.

Автор: inside_pointer 10.3.2009, 01:31
Цитата(leneCaress)

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


Код

SYNOPSIS
       #include <wctype.h>

       wint_t towupper(wint_t wc);



update:
добавил пример

Автор: leneCaress 10.3.2009, 07:29
о... интересно...

значит я могу перевести любую строку в текущей локали в wchar_t с помощью mbsrtowcs, и обратно - в текущую локаль с помощью wcsrtombs....

здорово...

но получается заморочка: pcre работает с utf8, но не wchar... ну вообщем если дойдет до регэкспов - придется наверное туда-сюда конвертить?


спасибо за наводку

Автор: inside_pointer 10.3.2009, 09:44
Цитата(leneCaress)

но получается заморочка: pcre работает с utf8


Код

[guest@station ~]$ cd /usr/include
[guest@station include]$ FindWord wchar_t | grep typedef
./curses.h:typedef unsigned short wchar_t1;
./ncurses/curses.h:typedef unsigned short wchar_t1;
./ncurses/ncurses.h:typedef unsigned short wchar_t1;
./ncursesw/curses.h:typedef unsigned short wchar_t1;
./ncursesw/ncurses.h:typedef unsigned short wchar_t1;
./X11/Xlib.h:typedef unsigned long wchar_t;



utf8 ?

Автор: azesmcar 10.3.2009, 11:33
Цитата

раньше пользовалась printf для форматирования строк. думаю что теперь перейду на потоки.


не надо думать smile переходите однозначно, printf это не C++, это - C и он небезопасен.
Цитата

сейчас задача формулируется примерно так: есть большой(>500Mb) объем текстовых данных, висящих у меня в памяти (строки в однобайтовой кодировке или в utf8, кодировка конткретного файла известна),


обычно текстовые файлы в начале хранят BOM (Byte-order mark), в присланной мной теме есть ссылки на эту тему. Проверьте ваши файлы - чтобы не читать Byte-order mark как часть текста.

Цитата

например, самое простое, взять только первые 5 символов и перевести их в верхний регистр...


сковертируйте в std::wstring а там уже посмотрите функции стандартной библиотеки для работы с std::wstring.

Цитата

например, самое простое, взять только первые 5 символов и перевести их в верхний регистр...


Код

std::wstring t = L"Привет мир!";
std::transform(t.begin(), t.begin() + 5, t.begin(), towupper);


Добавлено через 1 минуту и 49 секунд
http://unicode.org/faq/utf_bom.html

тут тоже много полезного

Автор: leneCaress 10.3.2009, 12:02
Цитата(azesmcar @  10.3.2009,  11:33 Найти цитируемый пост)
не надо думать smile переходите однозначно, printf это не C++, это - C и он небезопасен.


а по производительности оно как?
если нужно много строк форматировать?
(или сильно зависит от реализации?)


Цитата(azesmcar @  10.3.2009,  11:33 Найти цитируемый пост)
обычно текстовые файлы в начале хранят BOM (Byte-order mark)

знаю такого зверя =)
кстати, с BOM сталкивалась только на файлах пришедших с win.



Огромное спасибо!!!
Осилила задачу =)

Автор: azesmcar 10.3.2009, 12:15
Цитата

а по производительности оно как?
если нужно много строк форматировать?
(или сильно зависит от реализации?)


думаю если вас заботит разница в производительности между printf и std::cout то вы не тот язык программирования выбрали smile вам сюда
http://forum.vingrad.ru/forum/ASM-forum.html

smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)