Конкатенация строк, содержащих арабские и западные символы

#java #string #internationalization #arabic

#java #строка #интернационализация #Арабский

Вопрос:

Я пытаюсь объединить несколько строк, содержащих как арабские, так и западные символы (смешанные в одной строке). Проблема в том, что результатом является строка, которая, скорее всего, семантически правильная, но отличается от того, что я хочу получить, потому что порядок символов изменен двунаправленным алгоритмом Unicode. В принципе, я просто хочу объединить, как если бы все они были LTR, игнорируя тот факт, что некоторые из них являются RTL, своего рода «независимой» конкатенацией.

Я не уверен, ясно ли я выразился в своем объяснении, но я не думаю, что смогу сделать это лучше.

Надеюсь, кто-нибудь сможет мне помочь.

С уважением,

Carlos Ferreira

Кстати, строки получаются из базы данных.

Редактировать

введите описание изображения здесь

Первые 2 строки — это строки, которые я хочу объединить, а третья — результат.

ПРАВКА 2

На самом деле, объединенная строка немного отличается от той, что на изображении, она была изменена во время копирования вставки, 1 находится после первого A, а не непосредственно перед вторым A.

Комментарии:

1. Не могли бы вы отправить некоторые тестовые данные (т. Е. 2 строки).

2. Не могли бы вы показать нам несколько примеров?

3. Ну, я пытался, но когда я копирую строки, они изменяются.

4. Вы можете сделать снимок с помощью инструмента обрезки и вставить его сюда

Ответ №1:

Вы можете встраивать области bidi, используя управляющие кодовые точки формата Unicode:

  • Встраивание слева направо (U 202A)
  • Встраивание справа налево (U 202B)
  • Всплывающее форматирование в направлении (U 202C)

Итак, в Java для встраивания языка RTL, такого как арабский, в язык LTR, такой как английский, вы должны сделать

 myEnglishString   "u202B"   myArabicString   "u202C"   moreEnglish
  

и чтобы сделать обратное

 myArabicString   "u202A"   myEnglishString   "u202C"   moreArabic
  

Более подробную информацию см. в Общем двунаправленном форматировании или в главе спецификации Unicode «Коды направленного форматирования» для получения исходного материала.

Комментарии:

1. Есть ли способ в Java / Android удалить все такие символы и другие, которые на самом деле не будут отображаться при их печати? Мне это нужно для сортировки списка строк, но некоторые из них имеют специальный символ «u202B», который нарушает порядок элементов списка. Использование функции trim() не удаляет их.

2. @androiddeveloper, вашим лучшим выбором может быть удаление всех символов, кроме графических или интервальных, выполнив что-то вроде myString.replaceAll("[^ trn\p{Graph}] ", "") . Я не помню сразу, но использование категории Z за вычетом пробелов нулевой ширины, вероятно, является наилучшим приближением к «печатным» символам пробела.

3. Как насчет того, чтобы просмотреть каждый символ входной строки, и только если «Символ. isIdentifierIgnorable(c)» возвращает false, добавить его в новую строку? Этого будет достаточно?

4. @androiddeveloper, если это то, чего ты хочешь, то .replaceAll("[\p{identifier ignorable}] ", "") должен это сделать.

5. Это делает то же самое? Вопрос в том, является ли эта функция вообще правильной для использования для очистки таких специальных символов и, возможно, других. При тестировании кажется, что это так, но я хочу быть уверен.

Ответ №2:

Очень вероятно, что вам нужно вставить коды направленного форматирования Unicode в вашу строку, чтобы получить правильное отображение строки. Для получения подробной информации см. Коды направленного форматирования спецификации двунаправленного алгоритма Unicode.

Возможно, класс Bidi может помочь вам в определении правильной последовательности, поскольку он реализует двунаправленный алгоритм Unicode.

Комментарии:

1. Класс Bidi помогает определить последовательность, но я не знаю, как я могу заставить его обрабатывать строку как LTR вместо RTL. Но я посмотрю на ссылку, которую вы упомянули, может быть, я смогу разобраться в этом. Спасибо.

2. У меня нет никакого опыта в этом, но, похоже, вам придется использовать комбинацию неявных меток направления LRM (U 200E) и RLM (U 200F), которые не отображаются, и ограничителя кода направления PDF (U 202C). Также есть онлайн-демонстрация на unicode.org/cldr/utility/bidi.jsp , где вы можете протестировать все.

3. @MicSim у меня это сработало, и спасибо, что указали мне правильное направление. Это не было интуитивно понятным. Я использовал класс Bidi.requiresBidi(...) в if / else, затем сделал это: StringBuilder stbr = new StringBuilder(); stbr.append("u200e"); //"LRM"<--@start string stbr.append( cl.get(c).getPosition() " " ); stbr.append("u202b"); //"RLE" open tag, RTL text is next stbr.append( cl.get(c).getName() ); //<--Arabic name stbr.append("u202c"); //"PDF" close tag, RTL text was inserted cont LtoR... Разница заключалась в LRM в начале.

Ответ №3:

Это не меняет порядок кодовых точек. Что происходит, так это то, что когда дело доходит до отображения строки, он видит, что строка начинается со скрипта справа налево, поэтому он отображает ее справа налево.

Комментарии:

1. Я знаю, что это не меняет порядок, но как я могу предотвратить такое поведение?