BreakIterator如何在Android中工作?

问题描述:

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

我在学习如何使用它。 documentation比平均值更有帮助,但从阅读起仍然很难理解。我还发现了一些教程(请参阅here,herehere),但他们缺少完整的解释并输出了我正在寻找的内容。

我在添加此Q &风格答案以帮助我学习如何使用BreakIterator

除了Java之外,我还将其制作为Android标记,因为它们之间有apparently some difference。此外,Android现在支持ICU 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在Android中。我使用的是System.out.println而不是Log,因此它也可以在仅Java环境中测试。

我使用的是java.text.BreakIterator而非ICU,它只能从API 24中获得。请参阅底部的链接了解更多信息。

人物

更改样板代码包括以下

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

输出

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

最让人感兴趣的部分是在指标6810。您的浏览器可能会正确显示字符,但可能会将所有这些字符都解释为单个字符,即使它们是由多个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,在我的测试中仍然如此。

线

你可以保持代码相同的词如:

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(); 

输出

image to represent text output

正确的句子分解多种语言得到了承认。此外,电子邮件域中的点没有误报。

您可以设置Locale当你创建一个BreakIterator,但如果你不这样做,它只是使用了default locale

进一步阅读

+0

将中文文本分解为单词对我来说工作不正常。你能看看https://stackoverflow.com/questions/44507838/breakiterator-not-working-correctly-with-chinese-text吗? – srgsanky