我正在Android中制作自己的文本处理器(蒙古语的自定义垂直脚本TextView)。我以为自己必须找到所有换行位置,以便可以实现换行,但是后来发现 BreakIterator
。这似乎找到了各种语言中的字符,单词,行和句子之间的所有可能的中断。
我正在尝试学习如何使用它。 documentation比平均水平更有用,但仅通过阅读仍然很难理解。我还找到了一些教程(请参阅here,here和here),但是它们缺少我想要的输出的完整说明。
我添加了这个Q&A风格的答案,以帮助自己学习如何使用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;
}
如果您只是想测试一下,可以将其直接粘贴到Android中Activity的onCreate
中。我使用的是System.out.println
而不是Log
,因此它也可以在纯Java环境中进行测试。我使用的是
java.text.BreakIterator
而不是ICU(仅可从API 24获得的ICU)。有关更多信息,请参见底部的链接。性格
更改样板代码以包括以下内容
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 果。
请注意,中断位置不是整行文本。它们只是换行文本的便捷位置。输出类似于Words示例。但是,现在前面的单词中包含空格和标点符号。这是有道理的,因为您不希望换行以空格或标点符号开头。还要注意,汉字每个字符都会有换行符。这与在中文中跨行打破多字符单词是可以的。
句子
更改样板代码以包括以下内容:
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 我不爱吃臭豆腐。
正确的断句用多种语言识别。此外,电子邮件域中的点也没有误报。笔记
您可以在创建
BreakIterator
时设置Locale,但如果不这样做,则仅使用default locale即可。进一步阅读