Java國際化:BreakIterator

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統計特定語言中的單詞數Counting Words in a Specific Language in Java
這個Java代碼片段顯示瞭如果統計某個特定語言中的單詞數:

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() 需要一個 string 參數和一個 Locale 參數。Locale 代碼了傳入的string的語言類別。因此,當創建 BreakIterator,它可以創建針對那個語言類型的實例。

這個方法統計了一個單詞在傳入的串中有多少個,然後返回一個 Map<String, WordCount> 對象,Map中的key是一個一個單詞,以小寫形式表示,值是一個 WordCount 實例,它包含了兩個變量:word 和 count 。只需要把所有的單詞發生的次數相加就可以得到總的單詞數了。

注意:isWord() 方法中是怎麼使用 Character.isLetterOrDigit() 方法來判斷某個字符是字母還是數字的,或者是其他的(例如分號,引號等)。Character.isLetterOrDigit()方法檢查對應的unicode characters 是字母還是數字,並且不僅僅用在英語上,也可以用於其他語言。關於這個方法和其他的一些類似的方法的更詳細的描述,可以參考:Characeter Methods 。

句子邊界
對於特定語言的句子邊界,需要創建一個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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章