Hello! > Если нужна посимвольная обработка, определение типа (буква, знак препинания > и т.п.), преобразование (регистра, убирание акцента,…), то удобнее работать > с представлением, в котором размер каждого символа одинаков. Иначе всё > равно каждый символ пришлось бы преобразовывать при извлечении из строки. > Да и индексация, замена возможны. > > Но для этого совершенно не подходят старые функции работы со строками, > программу нужно писать по-другому. > > Если же достаточно ввода/вывода, запросить у пользователя имя, вывести его > же, или сохранить в файле, чтобы вывести после, то удобнее использовать > UTF-8. При этом не нужно переписывать полностью старые программы, > большинству вообще не нужна переделка. Большинство функций для работы с > 8-битовыми строками будут с таким же успехом работать и с UTF-8 (а вот > UTF-16 и UTF-32 не подойдут), по крайней мере в старой области значений. > > Поэтому UTF-8 используют как стандартное внешнее представление (чтобы с > данными работали другие программы) и как внутреннее, если не нужна сложная > работа со строками, учитывающая уникодность.
Спасибо за подробное объяснение. Вопрос в том, что движок СУБД SQLite, с которой я работаю, имеет два внутренних представления - utf8 и utf16. Во втором случае я могу пользоваться системными функциями для преобразования и сравнения символов (строк), а вот в случае utf8 не получается. Делать лишние преобразования чревато определенными потерями в производительности на всех сортировках/сравнениях текстовых данных. Сам движок умеет разделять строку utf8 на символы, остается добавить функции сравнения/преобразования регистров. Данных в utf16 у меня сейчас нет, поскольку база заполняется при локали системы UTF-8. После ваших подсказок появилась мысль, что для utf8 можно сделать локале-независимую, а для utf16 - локале-зависимую реализации и выбирать формат хранения данных в зависимости от потребностей. Может быть, вы можете дать оценку такому варианту? Я не тестировал скорость обработки utf8/utf16, но по таблицам символов должно быть все равно, какое представление выбрано, если таблицы составлены в нем же, а системные функции быстрее должны работать с utf16, но размер данных увеличится... > > Про UTF-16BE я уже понял, но вот буква Ё пропадает. А если через iconv > > передавать, все ок. > > А откуда ты берёшь Ё в UTF-16BE? Ты уверен, что это именно Ё? Подозреваю, > что ты ошибся с преобразованием. Ни "Ё", ни L"Ё" не даст тебе Ё в UTF-16BE > на большинстве систем (к которым ты имеешь доступ). Уверен, поскольку могу указать явно, в каком формате мне нужны данные - sqlite3_value_text16, sqlite3_value_text16be, sqlite3_value_text16le, sqlite3_value_text (последняя функция вернет utf-8). Вызов unac_string работает корректно, а unac_string_utf16 "ломает" данные. void unaccFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char *z1 = 0; const char *z2; int n, l = 0; if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z2 = (const char*)sqlite3_value_text16(argv[0]); n = sqlite3_value_bytes16(argv[0]); /* Verify that the call to _bytes16() does not invalidate the _text16() pointer */ assert( z2==(char*)sqlite3_value_text16(argv[0]) ); if( z2 ){ //unac_string("UTF-8", z2, n, &z1, &l); if(unac_string("UTF-16", z2, n, &z1, &l) == -1) { sqlite3_result_null; return; } //unac_string_utf16(z2, n, &z1, &l); sqlite3_result_text16(context, z1, l, SQLITE_TRANSIENT); } } > > Как сделать "в один ход" > > сравнение multibyte строк (символов)? В примерах, что я видел, > > разработчики таскают с собой таблицы для сравнения юникодных символов, > > зато могут работать с многобайтовыми строками, не занимаясь бесконечными > > преобразованиями. > > Чтобы посимвольно сравнивать многобайтовые строки, необходимо посимвольно > извлекать из них символы для сравнения (с/без учётом акцентов, регистров и > т.п.). Т.е. декодировать последовательно каждую из строк. Для каждого > сравнения. Все строки. > > Но если нам не нужен алфавитный порядок, если нужно просто упорядочить > строки (для деревьев, для бинарного поиска), то можем просто использовать > strcmp для многобайтовых строк в UTF-8. UTF-8 имеет такое свойство, что > результат этого сравнения будет совпадать с результатом посимвольного > сравнения кодов уникодных символов. Да, так оно и сделано по умолчанию, но мне нужно сортировать по алфавиту (игнорируя акценты у "ё" и "й"), делать регистронезависимый поиск и приведение регистра. Впрочем, без учета системной локали это делается "в лоб" с помощью таблиц символов. P.S. Кстати, напоминаю, что продолжаю писать и собирать дополнительные модули для SQLite. Для работы с юникодом сейчас есть две реализации - таблицы преобразований и через libicu, думаю насчет локале-зависимой, но от последней пока только функции upper/lower сделаны :-) Недавно добавил сибэйзовскую функцию current_user() для облегчения миграции на эскулайт и обращение к переменным окружения. Если кому надо или есть свои наработки - милости просим. Best regards, Alexey. -- To UNSUBSCRIBE, email to debian-russian-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org