BreakIterator如何在Android中运行?

我正在Android中创建自己的文本处理器(一个自定义垂直脚本TextView for Mongolian)。 我想我必须自己找到所有的断线位置,以便我可以实现换行,但后来我发现了BreakIterator 。 这似乎找到了各种语言中的字符,单词,行和句子之间的所有可能的中断。

我正在努力学习如何使用它。 文档比平均更有帮助,但仅仅通过阅读仍然难以理解。 我还找到了一些教程(见这里 , 这里和这里 ),但他们缺乏我正在寻找的输出的完整解释。

我正在添加这个Q&A风格的答案,以帮助自己学习如何使用BreakIterator

除了Java之外,我正在制作这个Android标签,因为它们之间显然存在一些差异 。 此外,Android现在支持ICU BreakIterator ,未来的答案可能会解决这个问题。

BreakIterator可用于查找字符,单词,行和句子之间可能的中断。 这对于将光标移动到可见字符,双击以选择单词,三击以选择句子和换行等内容非常有用。

Boilerplate代码

以下示例中使用了以下代码。 只需调整第一部分即可更改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; } 

如果您只想测试一下,可以将其直接粘贴到Android中的Activity的onCreate中。 我正在使用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 . 

最感兴趣的部分是索引610 。 您的浏览器可能会或可能不会正确显示字符,但用户会将所有这些字符解释为单个字符,即使它们由多个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 果。 

请注意,中断位置不是整行文本。 它们只是换行文本的便利位置。

输出类似于Words示例。 但是,现在前面的单词中包含空格和标点符号。 这是有道理的,因为您不希望新行以空格或标点符号开头。 另请注意,中文字符会为每个字符提供换行符。 这与在中文中跨行打破多字符单词的事实是一致的。

句子

更改样板代码以包含以下内容:

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

产量

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

以多种语言识别正确的句子rest时间。 此外,电子邮件域中的点没有误报。

笔记

您可以在创建BreakIterator时设置区域设置 ,但如果不这样做, BreakIterator使用默认区域设置 。

进一步阅读

  • 文档
  • ICU版BreakIterator
  • 这是一个更有用的教程。