2009-11-04 13 views
7

Piszę aplikację java; ale utknąłem w tym punkcie.Aby podzielić tylko chińskie znaki w java

Zasadniczo mam ciąg znaków chińskich z również kilka możliwych łacińskich znaków lub numerów, powiedzmy:

查詢促進民間參與公共建設法(210BOT法). 

chcę podzielić te chińskie znaki z wyjątkiem łaciny lub numerów jak „bot” powyżej. Tak, w końcu będę mieć tego rodzaju listy:

[ 查, 詢, 促, 進, 民, 間, 參, 與, 公, 共, 建, 設, 法, (, 210, BOT, 法, ), ., ]

Jak mogę rozwiązać ten problem (dla Java)?

Odpowiedz

10

chińskich znaków Unicode leży w określonym zakresie:

  • 2F00-2FDF: Kangxi
  • 4E00-9FAF: CJK
  • 3400-4DBF: CJK Rozszerzenie

więc wszystko co w zasadzie musisz sprawdzić, czy kodek znakowy znaku znajduje się w znanych zakresach. Ten przykład jest dobrym punktem wyjścia do napisania stackbased parsera/splitter, trzeba tylko przedłużyć go oddzielić od cyfry litery łacińskie, które powinny być na tyle oczywiste (podpowiedź: Character#isDigit()):

Set<UnicodeBlock> chineseUnicodeBlocks = new HashSet<UnicodeBlock>() {{ 
    add(UnicodeBlock.CJK_COMPATIBILITY); 
    add(UnicodeBlock.CJK_COMPATIBILITY_FORMS); 
    add(UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS); 
    add(UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT); 
    add(UnicodeBlock.CJK_RADICALS_SUPPLEMENT); 
    add(UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION); 
    add(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS); 
    add(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A); 
    add(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B); 
    add(UnicodeBlock.KANGXI_RADICALS); 
    add(UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS); 
}}; 

String mixedChinese = "查詢促進民間參與公共建設法(210BOT法)"; 

for (char c : mixedChinese.toCharArray()) { 
    if (chineseUnicodeBlocks.contains(UnicodeBlock.of(c))) { 
     System.out.println(c + " is chinese"); 
    } else { 
     System.out.println(c + " is not chinese"); 
    } 
} 

powodzenia.

+0

Jako rozszerzenie, wierzę klasę znaków w regexp. obejmują również powyższe zakresy unicode. –

+0

Niezupełnie, jeśli chcesz również przechwycić grupy cyfr/liter/łączników/cokolwiek innego. Parser oparty na stosie jest lepszym narzędziem do tego rodzaju pracy. – BalusC

+0

Czy to działa również w języku japońskim i koreańskim? –

1

Oto podejście, które brałbym.

Możesz użyć Character.codePointAt (char [] charArray, indeks int), aby zwrócić wartość Unicode dla znaku w tablicy znaków.

Potrzebne będzie również odwzorowanie łacińskich znaków Unicode.

Jeśli przyjrzeć się źródłu Character.UnicodeBlock, pełny blok LATIN jest przedziałem [0x0000, 0x0249]. Więc w zasadzie sprawdzasz, czy twój kod Unicode jest gdzieś w tym przedziale.

Podejrzewam, że istnieje sposób, aby po prostu użyć Character.Subset, aby sprawdzić, czy zawiera on znak, ale nie patrzyłem w to.

1

Diclaimer: Jestem kompletnym nowicjuszem Lucene.

Korzystając z najnowszej wersji Lucene (3.6.0 w chwili pisania tego tekstu) udaje mi się zbliżyć do wymaganego wyniku.

Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36, Collections.emptySet()); 

    List<String> words = new ArrayList<String>(); 
    TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(original)); 
    CharTermAttribute termAttribute = tokenStream.addAttribute(CharTermAttribute.class); 

    try { 
    tokenStream.reset(); // Resets this stream to the beginning. (Required) 
    while (tokenStream.incrementToken()) { 
     words.add(termAttribute.toString()); 
    } 
    tokenStream.end(); // Perform end-of-stream operations, e.g. set the final offset. 
    } 
    finally { 
    tokenStream.close(); // Release resources associated with this stream. 
    } 

Wynik pojawia się:

[查, 詢, 促, 進, 民, 間, 參, 與, 公, 共, 建, 設, 法, 210bot, 法] 
Powiązane problemy