Обработка строки в Юникоде с использованием Windows API - PullRequest
2 голосов
/ 25 ноября 2011

Я всегда предполагал, что обработка строк в Unicode - это какое-то темное искусство. Однако я видел, что в Windows API есть функции для сравнения строк Юникода, например. Означает ли это, что на самом деле возможно написать строковый класс Unicode, который может выполнять простые действия, такие как сортировка, сравнение на равенство и извлечение из файла? Или есть скрытые ошибки в использовании этих функций, которые делают его действительно плохой идеей? Я просто смотрю на такие библиотеки, как ICU, и они кажутся невероятно чрезмерно сложными по сравнению с тем, как на самом деле мог бы выглядеть класс строки Unicode, поддерживаемый Windows API, который очень близко напоминал бы классы стандартных строк.

Ответы [ 4 ]

3 голосов
/ 26 ноября 2011

Значит ли это, что на самом деле выполнимо написать строковый класс Unicode, который может выполнять простые действия, такие как сортировка, сравнение на равенство и извлечение из файла?

Да.C #, Java, .Net, Python, (список можно продолжить) имеют строки Unicode в качестве базовых типов, и даже C / C ++ с библиотеками, подобными ICU, имеют это.

Или есть скрытые ошибки виспользование этих функций, которое делает его действительно плохой идеей?

Да, есть ошибки.Меньше да на "плохую идею".Возьмем примеры, которые вы опубликовали: «сортировка, сравнение на равенство и извлечение из файла».

  • Извлечение из файла: Эта задача довольно проста, еслиВы знаете, в какой кодировке находится ваш файл. Большинство языков предоставляют некоторые средства для чтения файла и перевода из байтов в тип "Unicode" этого языка.(Например, в Python data = file_handle.read() для чтения из файла, затем data.decode(encoding_my_file_uses) возвращает мне строковый объект unicode. (Или str в Python 3)

  • Сравнение равенства: Здесь что-то немного раздражает. Основной строительный блок Unicode - это «кодовые точки». Строка Unicode - это не более чем последовательность кодовых точек. Однако Unicode включает в себя кодовые точки дляакценты, которые объединяются с предыдущим символом, но у него также есть некоторые кодовые точки с акцентом «предварительно составленный». Это может быть 2 кодовые точки (e + accute) или 1 кодовая точка. Если у меня есть две строки, одна с двумя кодовыми точкамиверсия, и одна с версией 1 кодового пункта ... они одинаковы? Ответ может зависеть от того, что вы хотите. Аналогичным образом, если у вас есть персонаж с несколькими акцентами (обычно на вьетнамском языке), акценты могут быть в любом порядке.

    Ключ? Вы должны знать, какое равенство вы хотите. Операции равенства без учета регистра делают это еще более увлекательным, так как разные языкиУ нас разные представления о том, что такое буква в верхнем или нижнем регистре.Тем не менее, Unicode определяет и предоставляет методы для получения кодовых точек в определенных порядках (способ нормализации строк), чтобы упростить эти вещи.Такие библиотеки, как ICU, и даже стандартные библиотеки некоторых языков уже реализовали их для вас в различных функциях.

  • Сортировка: Сортировка во многом похожа на равенство.Вы должны знать, что вы действительно хотите.Порядок сортировки может зависеть от языка.Для меня ä и a оба являются «а» и должны быть отсортированы вместе, но это не всегда так.(Некоторые языки ставят ä после z.) Другой пример: где сортировка?Как говорящий по-английски, у меня нет хорошего ответа, кроме как «до или после всего остального».Самая простая сортировка - это просто сортировка по порядку кодовых точек, но она не дает ничего полезного для большинства людей.

    Ответ здесь аналогичен: Unicode определяет методы, как это сделать, и различные библиотеки (например, ICU).) реализовать эти методы.

ICU, например, должен иметь возможность для всего этого для вас относительно легко..Net также включает методы для этого.Хотя вышесказанное может показаться сложным, я обнаружил, что большая часть кода, который я когда-либо писал, не выполняет манипуляций, которые требуют больше всего вышеперечисленного.В большинстве случаев вы просто соединяете строки, чтобы создать какое-то выходное сообщение для пользователя: все, что вам нужно, - это хорошая процедура форматирования.(Как в Python unicode.format или .Net String.Format: все, что позволяет позиционную нотацию, такую ​​как "The {0} was in the {1}".) Редко, вам нужно отсортировать информацию для пользователя: это просто «выяснить подходящий язык для этого пользователя, сортироватьэтот массив, используя эту локаль, выведите. "

IЕсли вы никогда не использовали Unicode прежде, то первым большим шагом будет просто использовать его.В зависимости от вашего языка, вы уже можете, но просто не подозреваете об этом.Google для учебников, прочитайте статьи Википедии.Более важный ключ, IMHO, заключается в том, что если вы обрабатываете текстовые данные, вы должны знать, в какой кодировке они находятся. Сегодня этот ответ, если он известен, почти всегда "UTF-8"для сериализованных байтов или для содержимого памяти" UTF-16 "или" UTF-8 ".

0 голосов
/ 28 ноября 2011

Как уже указывалось другим, это не очень сложно и определенно не темное искусство.Но один комментарий: сортировка и сравнение на равенство не имеют ничего общего с Юникодом, как с местными соглашениями.Потому что это операции, чувствительные к локали.Например, немецкий сортирует вещи не так, как шведский, и не французский.

В Windows вы можете просто использовать CompareString (или CompareStringEx, если вы хотите использовать строковые идентификаторы языкового стандарта).Делает то же самое, что и ICU Collator (C ++) или ucol_strcoll (C).Время от времени вы получите немного разные результаты между Windows и ICU, потому что Windows все делала независимо (а иногда это хуже, чем ICU, но иногда лучше).

Но в целом все будет хорошо (намного лучше, чемнелокальное сравнение)

0 голосов
/ 26 ноября 2011

Танатос: Equality Comparision:... Я только частично согласен с этим пунктом.Я не согласен в том смысле, что это не характерно для Unicode.Этот вид сложности имеет коренную причину в локали, которую вы используете.Любая кодировка символов должна поддерживать такую ​​особенность языка, если она заявляет о поддержке соответствующей локали.И, конечно же, обеспечить поддержку чего-то подобного в библиотеке строковых классов (или наборе шрифтов) очень сложно.

Более того, такая поддержка возможна только в некоторой степени.Рассмотрим немецкий умляут 'ü'.Возможной заменой этого письма в немецком языке является комбинация букв «и».Слова «bügeln» (немецкий для глажения) и «buegeln» будут появляться в одном и том же месте в словаре.Попробуйте это в немецко - английском словаре на www.leo.org.Каждый, кто знает немецкий язык и значение слова «bügeln», поймет, что «buegeln» означает то же самое.

Это означает , а не означает, что ü = ue на немецком языке.Название «Ruegger», например, произносится как «Ru-egger» (нет, у него есть глотовая остановка), и если бы существовало такое слово, как «Rügger», то «Ruegger» появилось бы перед «Rügger» в словаре.(поскольку u и ü обычно считаются эквивалентными в том, что касается лексикографической сортировки, и e предшествует g).Вам нужно знать слова, чтобы отличить эту разницу.Этот тип специфической для языка сложности , а не из-за того, что любой может использовать юникод для кодирования символов, используемых для записи этого языка.Независимо от того, какую кодировку вы используете и какой класс строк вы используете, разработчик приложения должен знать специфику языка и то, как и в какой степени класс строк поддерживает их.

Большинство людей в англоязычном мире никогда не осознают этой сложности, потому что их язык не очень сложен в этом отношении, и они привыкли к сложности, с которой они сталкиваются в своей повседневной работе.(Просто скажите мне, почему в ASCII все заглавные буквы стоят перед строчными. Почему это не A, a, B, b, C, c? Это просто соглашение, к которому все привыкли. Это боль, если выНужно написать словарь, где А и А должны появиться в одном и том же месте).Когда дело доходит до юникода, эта сложность внезапно становится актуальной, потому что вы сталкиваетесь с концепцией, которая претендует на поддержку практически любой локали в мире.

Что имеет значение , тем не менее, это тот факт, что если вы переходите с какой-либо другой кодировки на Unicode, то вам необходимо учитывать, что такие вещи, как сортировка и проверки на равенство могут рассматриватьсяиначе в строковой библиотеке с поддержкой юникода.В частности, у вас есть все причины нервничать, если кто-то начинает говорить о переносе юникода для программного проекта с большим количеством строковых манипуляций.Такая миграция подразумевает множество домашних заданий, и одна из причин заключается именно в разнице, когда дело доходит до сортировки и проверки равенства строк.Другая причина заключается в том, что кодировкам Unicode требуется больше места, чем классическим кодировкам ANSI, что делает перенос символов ** настоящей головной болью.

0 голосов
/ 26 ноября 2011

Unicode - это путь в будущее, посмотрите, например, http://msdn.microsoft.com/en-us/library/windows/desktop/dd374089%28v=vs.85%29.aspx, где они уже говорят, что «некоторые более новые функции поддерживают только версии Unicode». Отметьте слово «новее». Строковые классы .Net, например, являются юникодом, как и строковые классы Java.

Использование юникода не темное искусство, на самом деле это делает работу с разными языками невероятно простой. В моем проекте свободного времени я использую JSP, чтобы принять пользовательский ввод для словаря на двух языках (по выбору пользователя), затем обработать их (сортировка, извлечение подстрок, поиск, объединение) в Java и, наконец, записать их в БД используя JDBC. После этого я могу искать и извлекать их из БД, обрабатывать их и отображать на странице http. Мне пришлось настроить свою среду разработки для поддержки UTF-8 и постоянно использовать UTF-8, но с того момента, как я это сделал, это работает для каждой раскладки языка / клавиатуры, которую поддерживает ОС, и я даже больше не буду беспокоиться. В том числе японский, арабский, деванагари, русский. Простой щелчок мыши меняет раскладку клавиатуры, и программа все равно работает. Это работает в Linux, Windows XP, Windows 7, будь то 32-битной или 64-битной. БД, которую я использую, поддерживает это во всех этих средах, в том числе и в среде dev (eclipse / Java). Мне просто не нужно больше заботиться. Конечно, если вы сортируете арабские строки, вы должны знать кое-что об арабском языке, об алгоритме сортировки и о сравнении строк для используемых вами классов строк. Но это обычно документируется.

Конфигурирование среды разработки означает, конечно, что вы знаете места, где это уместно. Они включают, но не ограничиваются классами строк, которые вы будете использовать, кодировкой, используемой вашим редактором, кодировкой шаблонов (для XML, HTML, файлов ресурсов и т. Д.), Таблицами базы данных ... Но однажды Вы настроили его, используя последовательно одну и только одну кодировку символов, это очень мощная и чрезвычайно простая в использовании настройка.

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

Смысл в том, чтобы последовательно использовать одну кодировку во всем решении. Если используются разные кодировки, и вы не знаете об этом, это может стать основной причиной серьезной головной боли. Если вы сознательно используете разные кодировки символов одновременно, и это работает правильно, то это, на самом деле, может быть близко к некоторому мрачному искусству :-) Что вам нужно будет использовать, если вам придется ссылаться на библиотеки, которые его не поддерживают , То же самое относится и к библиотекам, которые не используют его постоянно, конечно.

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

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