Java国际化:BreakIterator

时间:2020-01-09 10:35:22  来源:igfitidea点击:

" java.text.BreakIterator"类用于查找不同语言之间的字符,单词和句子边界。由于不同的语言使用不同的字符,单词和句子边界,仅搜索空格,逗号,句号,分号,冒号等是不够的。我们需要一种万无一失的方式来搜索不同语言的边界。 BreakIterator类提供了这一点。

创建一个BreakIterator

一个BreakIterator实例只能检测以下类型的边界之一:

  • 字符边界
  • 单词边界
  • 句子边界
  • 行边界

我们可以使用BreakIterator类中的相应工厂方法创建一个可以识别上述边界之一的实例。出厂方法是:

BreakIterator.getCharacterInstance();
BreakIterator.getWordInstance();
BreakIterator.getSentenceInstance();
BreakIterator.getLineInstance();

这些方法中的每一个都以Locale作为参数,并返回一个BreakIterator实例。这是一个简单的示例:

Locale locale = LocaleUK;

BreakIterator breakIterator =
    BreakIterator.characterInstance(locale);

字符边界

搜索字符边界时,有必要区分用户字符和unicode字符。

用户角色是用户使用笔会写的角色。用户角色通常也是用户在屏幕上看到的内容。

它可能需要一个或者多个unicode字符来表示用户字符。某些用户字符由2个或者更多unicode字符表示。

BreakIterator类的字符实例查找用户字符而不是unicode字符的字符边界。

这是一个简单的示例,可查找字符串中的字符边界:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getCharacterInstance(locale);

breakIterator.setText("Mary had a little Android device.");

int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
    System.out.println(boundaryIndex) ;
    boundaryIndex = breakIterator.next();
}

这个例子创建了一个针对英国语言的BreakIterator,并设置了文本以使用setText()方法查找字符中断。

方法" first()"返回找到的第一个中断。方法" next()"查找所有后续中断。两种方法都返回找到的用户字符的unicode字符索引。因此,如果一个用户字符占用一个以上的unicode字符,则字符索引将随用户所使用的unicode字符的数量而增加。

词边界

找到单词边界时,我们需要创建一个BreakIterator,它能够为所需的特定语言找到单词边界。这是操作方式:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getWordInstance(locale);

这段代码创建了一个BreakIterator实例,可以在英国英语文本中查找单词边界。

这是一个在英语文本中查找单词边界的示例:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getWordInstance(locale);

breakIterator.setText("Mary had a little Android device.");

int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
    System.out.println(boundaryIndex) ;
    boundaryIndex = breakIterator.next();
}

同样,这里的first()和next()方法返回找到的单词边界的unicode索引。

用Java计算特定语言中的单词

这是一个Java代码示例,该示例显示了如何根据特定Locale的规则计算给定字符串中单词出现的次数:

public class WordCounter {

    public static class  WordCount {
        protected String word  = null;
        protected int    count = 0;
    }

    public static Map<String, WordCount> countWords(String text, Locale locale) {
        Map<String, WordCount> wordCounts = new HashMap<String, WordCount>();

        BreakIterator breakIterator = BreakIterator.getWordInstance(locale) ;
        breakIterator.setText(text);

        int wordBoundaryIndex = breakIterator.first();
        int prevIndex         = 0;
        while(wordBoundaryIndex != BreakIterator.DONE){
            String word = text.substring(prevIndex, wordBoundaryIndex).toLowerCase();
            if(isWord(word)) {
                WordCount wordCount = wordCounts.get(word);
                if(wordCount == null) {
                    wordCount = new WordCount();
                    wordCount.word = word;
                }
                wordCount.count++;
                wordCounts.put(word, wordCount);
            }
            prevIndex = wordBoundaryIndex;
            wordBoundaryIndex = breakIterator.next();
        }

        return wordCounts;
    }

    private static boolean isWord(String word) {
        if(word.length() == 1){
            return Character.isLetterOrDigit(word.charAt(0));
        }
        return !"".equals(word.trim());
    }
}

countWords()方法采用一个字符串和一个Locale。 Locale代表字符串的语言。因此,当创建BreakIterator时,可以为该特定语言创建它。

该方法计算每个单词在字符串中出现的次数,并将其作为Map <String,WordCount>返回。映射中的键是小写的单个单词。每个键的值是一个" WordCount"实例,其中包含两个变量:单词" word"和该单词的" count"。如果要获取文本中的单词总数,则必须对所有单个单词的计数求和。

请注意,isWord()方法如何使用Character.isLetterOrDigit()方法来确定字符是字母还是数字,还是其他(例如分号,引号等)。 Character.isLetterOrDigit()根据Unicode字符检查字符是字母还是数字,因此不仅是英语,还包括其他语言。 Characeter方法文本中对此方法和类似方法进行了更详细的描述。

句子边界

要定位句子边界,我们需要一个能够发现句子边界的BreakIterator实例。这是操作方式:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getSentenceInstance(locale);

这段代码创建了一个针对英国英语的BreakIterator

这是一个在英语字符串中查找句子边界的示例:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getSentenceInstance(locale);

breakIterator.setText(
        "Mary had a little Android device. " +
        "It had small batteries too.");

int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
    System.out.println(boundaryIndex) ;
    boundaryIndex = breakIterator.next();
}

行边界

我们可以在字符串中找到分行符,在该字符串中可以将一行文本分到一个新行中,而不会影响文本的阅读。为此,我们需要一个能够检测潜在断行的BreakIterator。请注意,它不会在文本中找到实际的换行符,而是可能的换行符。查找潜在的换行符对于在文本编辑器中很有用,即使文本不包含任何明确的换行符,文本编辑器在显示时也需要将其分成多行。这是创建这样的BreakIterator的方法:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getLineInstance(locale);

这个例子创建了一个" BreakIterator",它能够在英国英文文本中找到潜在的换行符。

下面是一个示例,该示例在带有英文文本的字符串中查找潜在的换行符:

Locale locale = Locale.UK;
BreakIterator breakIterator =
        BreakIterator.getLineInstance(locale);

breakIterator.setText(
        "Mary had a little Android device.\n " +
        "It had small batteries too.");

int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
    System.out.println(boundaryIndex) ;
    boundaryIndex = breakIterator.next();
}