Как работает BreakIterator в Android?

Я делаю свой собственный текстовый процессор в Android (собственный вертикальный скрипт TextView для монгольского). Я думал, что мне придется найти все линии, разбивающие локации, чтобы я мог реализовать перенос строк, но затем я обнаружил BreakIterator . Кажется, это находит все возможные разрывы между символами, словами, строками и предложениями на разных языках.

Я пытаюсь научиться его использовать. Документация была более полезной, чем средняя, ​​но ее было трудно понять, просто прочитав. Я также нашел несколько руководств (см. Здесь , здесь и здесь ), но у них не было полного объяснения с результатами, которые я искал.

Я добавляю этот ответ типа Q & A, чтобы помочь себе узнать, как использовать BreakIterator .

Я делаю это тегом Android в дополнение к Java, потому что, по- видимому, существует разница между ними. Кроме того, Android теперь поддерживает BreakIterator и в будущем ответы могут быть BreakIterator .

BreakIterator может использоваться для поиска возможных разрывов между символами, словами, строками и предложениями. Это полезно для таких вещей, как перемещение курсора через видимые символы, двойное нажатие для выбора слов, тройной щелчок для выбора предложений и обтекание строк.

Код котла

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

 // change these two lines for the following examples String text = "This is some text."; BreakIterator boundary = BreakIterator.getCharacterInstance(); // boiler plate code boundary.setText(text); int start = boundary.first(); for (int end = boundary.next(); end != BreakIterator.DONE; end = boundary.next()) { System.out.println(start + " " + text.substring(start, end)); start = end; } 

Если вы просто хотите проверить это, вы можете вставить его непосредственно в onCreate для onCreate на Android. Я использую System.out.println а не Log чтобы он также проверялся в среде Java.

Я использую java.text.BreakIterator а не ICU, который доступен только из API 24. Для получения дополнительной информации см. Ссылки внизу.

Персонажи

Измените код шаблона, чтобы включить следующее

 String text = "Hi 中文éé\uD83D\uDE00\uD83C\uDDEE\uD83C\uDDF3."; BreakIterator breakIterator = BreakIterator.getCharacterInstance(); 

Вывод

 0 H 1 i 2 3 中4 文5 é 6 é 8 😀 10 🇮🇳 14 . 

Наиболее интересными являются части 6 , 8 и 10 . Ваш браузер может или не может отображать символы правильно, но пользователь будет интерпретировать их все как отдельные символы, даже если они состоят из нескольких значений UTF-16.

слова

Измените код шаблона, чтобы включить следующее:

 String text = "I like to eat apples. 我喜欢吃苹果。"; BreakIterator boundary = BreakIterator.getWordInstance(); 

Вывод

 0 I 1 2 like 6 7 to 9 10 eat 13 14 apples 20 . 21 22 我23 喜欢25 吃26 苹果28 。 

Здесь есть несколько интересных вещей. Во-первых, разрыв слов обнаруживается с обеих сторон пространства. Во-вторых, несмотря на то, что существуют разные языки, все еще признавались многосимвольные китайские слова. Это было по-прежнему справедливо в моих тестах, даже когда я установил локаль в Locale.US .

линии

Вы можете сохранить код таким же, как для примера Words:

 String text = "I like to eat apples. 我喜欢吃苹果。"; BreakIterator boundary = BreakIterator.getLineInstance(); 

Вывод

 0 I 2 like 7 to 10 eat 14 apples. 22 我23 喜24 欢25 吃26 苹27 果。 

Обратите внимание, что места разломов не являются целыми строками текста. Это просто удобные места для текстового переноса текста.

Результат аналогичен примеру слов. Однако теперь перед пробелом добавляется пробел и пунктуация. Это имеет смысл, потому что вы не хотите, чтобы новая строка начиналась с пробела или пунктуации. Также обратите внимание, что китайские символы получают разрывы строк для каждого персонажа. Это согласуется с тем фактом, что хорошо сломать многосимвольные слова по строкам на китайском языке.

Предложения

Измените код шаблона, чтобы включить следующее:

 String text = "I like to eat apples. My email is [email protected]\n" + "This is a new paragraph. 我喜欢吃苹果。我不爱吃臭豆腐。"; BreakIterator boundary = BreakIterator.getSentenceInstance(); 

Вывод

 0 I like to eat apples. 22 My email is [email protected] 50 This is a new paragraph. 75 我喜欢吃苹果。 82 我不爱吃臭豆腐。 

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

Заметки

Вы можете установить Locale при создании BreakIterator , но если вы этого не сделаете, он просто использует локаль по умолчанию .

дальнейшее чтение

  • Документация
  • Версия ICU для BreakIterator
  • Это был один из самых полезных уроков.
  • Хостинг исполняемого файла в приложении Android
  • Пользовательские шрифты и XML-макеты (Android)
  • Stream Live Android Audio на сервер
  • почему MenuItemCompat.getActionProvider возвращает значение null?
  • Код для загрузки видео с Youtube на Java, Android
  • Использование шаблона проектирования Singleton для SQLiteDatabase
  • Максимальный предел примитивного типа Java Long
  • java рисует прямоугольник в одну сторону не одновременно
  • Добавить ярлык для приложения для Android. На главный экран.
  • Передача пользовательских объектов между действиями?
  • как проверить версию jdk, используемую для компиляции файла .class
  • Давайте будем гением компьютера.