Нечувствительное к регистру хранилище и юникод совместимость - PullRequest
14 голосов
/ 09 августа 2011

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

  • Тест Турции (в частности, изменение локали на работающем компьютере)
  • Обновления версии Unicode - Я имею в виду, кто знает об этом? Если я обновлюсь до Java 7, мне придется переиндексировать мои данные, если я не чувствую к регистру?

На какие технологии влияют версии Unicode?

Нужно ли беспокоиться о том, чтобы Oracle или SQL Server (или другие поставщики) изменили свои версии Unicode и в результате одна из моих локалей не привела к одинаковому преобразованию нижнего или верхнего символа?

Как мне управлять этим? Меня соблазняет «простота» обеспечения того, что я использую преобразование базы данных, но когда произойдет обновление, возникнет та же проблема.

Ответы [ 3 ]

34 голосов
/ 09 августа 2011

Вы не хотите хранить строчную версию строки «для поиска» !!

Это совершенно неправильный подход.Вы делаете несправедливые и неправильные предположения о том, как работает корпус Unicode.

Вот почему Unicode определяет отдельную вещь, называемую casefold для строки, отличную от трех разных падежей (строчные, заглавные и прописные).

Вот десять различных примеров , где вы будете делать неправильные вещи , если вы будете использовать строчные буквы вместо casefold:

ORIGINAL        CASEFOLD        LOWERCASE   TITLECASE  UPPERCASE
========================================================================
efficient         efficient       efficient       Efficient         EFFICIENT       
flour            flour           flour           Flour           FLOUR           
poſt            post            poſt           Poſt            POST            
poſt             post            poſt             Poſt            POST            
ſtop             stop            ſtop            Stop            STOP            
tschüß          tschüss         tschüß         Tschüß         TSCHÜSS         
weiß            weiss           weiß           Weiß            WEISS           
WEIẞ            weiss           weiß            Weiß           WEIẞ            
στιγμας         στιγμασ         στιγμας         Στιγμας         ΣΤΙΓΜΑΣ 
ᾲ στο διάολο    ὰι στο διάολο   ᾲ στο διάολο    Ὰͅ Στο Διάολο   ᾺΙ ΣΤΟ ΔΙΆΟΛΟ        

И да, я знаю множественное числостигмы это стигматы, а не стигмы;Я пытаюсь показать последнюю проблему сигмы.И ς, и σ являются действительными строчными версиями заглавной сигмы Σ.Если вы храните «только строчные буквы», то вы получите не то, что нужно.

Если вы используете класс Java Pattern, вы должны указать и CASE_INSENSITIVE, и UNICODE_CASE, и вы все равно не получите это право, потому что, хотя Java использует полное сопоставление регистра, оно использует только простое сложение регистра. Это проблема.

Что касается тюркских языков, то да, это правда, что для тюрков есть особый случай.Например, Стамбул имеет тюркскую заглавную букву Стамбул вместо Стамбул , которую вы должны получить.Поскольку я уверен, что они не будут выглядеть правильно для вас, я изложу это с именованными символами для не ASCII;Проще говоря, "\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}stanbul" имеет тюркское складывание "\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}stanbul" вместо "i\N{COMBINING DOT ABOVE}stanbul", которое вы обычно получаете.

Вот еще пара строк таблицы, если вы пишете набор для регрессионного тестирования:

[ "Henry Ⅷ", "henry ⅷ", "henry ⅷ", "Henry Ⅷ", "HENRY Ⅷ",  ],
[ "I Work At Ⓚ",  "i work at ⓚ",  "i work at ⓚ", "I Work At Ⓚ", "I WORK AT Ⓚ", ],
[ "ʀᴀʀᴇ", "ʀᴀʀᴇ", "ʀᴀʀᴇ", "Ʀᴀʀᴇ", "ƦᴀƦᴇ",  ],
[ "Ԧԧ", "ԧԧ", "ԧԧ", "Ԧԧ", "ԦԦ",   ],
[ "???????", "???????", "???????", "???????", "???????",   ],
[ "Ὰͅ", "ὰι", "ᾲ", "Ὰͅ", "ᾺΙ",  ],

Где каждый столбец - это orig, fold, lc, tc и uc, как я и делал в предыдущей таблице выше.Еще раз обратите внимание, что в последней строке есть регистр, отличающийся от строчного.

1 голос
/ 09 августа 2011

Укажите локаль для toLowerCase () вместо использования системы по умолчанию. Это защищает от изменений в системной локали.

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

0 голосов
/ 09 августа 2011

Я думаю, что наиболее долгосрочное решение -

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

Очевидно, это должно произойти науровень основного интерфейса;если я делаю эти изменения в Java, я лучше надеюсь, что это мой единственный механизм интерфейса данных (например, что другие специалисты не запрашивают базовое хранилище таблиц)

...