2011-04-25 68 views
2

我想在Android上通过递归目录搜索将搜索字符串与文件名匹配。问题是这些字符是日语,并且在某些情况下不匹配。例如,我试图匹配文件名称的开头的搜索字符串是“呼ぶ”。当我从file.getName()打印文件名时,这是准确反映的,例如打印到控制台的文件名称以“呼ぶ”开头。但是当我在搜索字符串上进行匹配时,例如fileName.startwith(“呼ぶ”),它不匹配。Android,日文字符文件名比较问题

事实证明,当我打印正在搜索的文件名的子字符串时,第二个字符不同 - 单词是“呼ふ”而不是“呼ぶ”。如果我提取字节并打印十六进制字符,则最后一个字节会关闭1 - 大概是“ぶ”和“ふ”之间的差异。

这里是用来以示区别的代码:

String name = soundFile.getName(); 
    String string1 = question.kanji; 


    Log.d(TAG, "searching for : s1:" + question.kanji + " + " + question.hiragana + " + " + question.english); 
    Log.d(TAG, "name is: " + name); 

    Log.d(TAG, "question.kanaji.length(): " + question.kanji.length()); 
    Log.d(TAG, "question.hiragana.length(): " + question.hiragana.length()); 


    String compareStart = name.substring(0, string1.length()); 

    Log.d(TAG, "string1.length(): " + string1.length()); 
    Log.d(TAG, "compareStart.length(): " + compareStart.length());  

     byte[] nameUTF8 = null; 
    byte[] s1UTF8 = null; 
    byte[] csUTF8 = null; 

    nameUTF8 = name.getBytes(); 
    s1UTF8 = string1.getBytes(); 
    csUTF8 = compareStart.getBytes(); 


    Log.d(TAG, "nameUTF8.length: " + s1UTF8.length);    
    Log.d(TAG, "s1UTF8.length: " + s1UTF8.length); 
    Log.d(TAG, "csUTF8.length: " + csUTF8.length); 

    for (int i = 0; i < s1UTF8.length; i++) { 
     Log.d(TAG, "s1UTF8[i]: " + Integer.toString(s1UTF8[i] & 0xff, 16).toUpperCase()); 
    } 

    for (int i = 0; i < csUTF8.length; i++) { 
     Log.d(TAG, "csUTF8[i]: " + Integer.toString(csUTF8[i] & 0xff, 16).toUpperCase()); 
    } 

    for (int i = 0; i < nameUTF8.length; i++) { 
     Log.d(TAG, "nameUTF8[i]: " + Integer.toString(nameUTF8[i] & 0xff, 16).toUpperCase()); 
    } 

的部分输出如下:

D/AnswerView(12078): searching for : s1:呼ぶ + よぶ + to call out,to invite 
D/AnswerView(12078): name is: 呼ぶ              よぶ     to call out,to invite.mp3 
D/AnswerView(12078): question.kanaji.length(): 2 
D/AnswerView(12078): question.hiragana.length(): 2 
D/AnswerView(12078): string1: 呼ぶ 
D/AnswerView(12078): compareStart: 呼ふ 
D/AnswerView(12078): string1.length(): 2 
D/AnswerView(12078): compareStart.length(): 2 
D/AnswerView(12078): string1.length(): 2 
D/AnswerView(12078): compareStart.length(): 2 
D/AnswerView(12078): nameUTF8.length: 6 
D/AnswerView(12078): s1UTF8.length: 6 
D/AnswerView(12078): csUTF8.length: 6 
D/AnswerView(12078): s1UTF8[i]: E5 
D/AnswerView(12078): s1UTF8[i]: 91 
D/AnswerView(12078): s1UTF8[i]: BC 
D/AnswerView(12078): s1UTF8[i]: E3 
D/AnswerView(12078): s1UTF8[i]: 81 
D/AnswerView(12078): s1UTF8[i]: B6 
D/AnswerView(12078): csUTF8[i]: E5 
D/AnswerView(12078): csUTF8[i]: 91 
D/AnswerView(12078): csUTF8[i]: BC 
D/AnswerView(12078): csUTF8[i]: E3 
D/AnswerView(12078): csUTF8[i]: 81 
D/AnswerView(12078): csUTF8[i]: B5 
D/AnswerView(12078): nameUTF8[i]: E5 
D/AnswerView(12078): nameUTF8[i]: 91 
D/AnswerView(12078): nameUTF8[i]: BC 
D/AnswerView(12078): nameUTF8[i]: E3 
D/AnswerView(12078): nameUTF8[i]: 81 
D/AnswerView(12078): nameUTF8[i]: B5 
D/AnswerView(12078): nameUTF8[i]: E3 
D/AnswerView(12078): nameUTF8[i]: 82 
D/AnswerView(12078): nameUTF8[i]: 99 
D/AnswerView(12078): nameUTF8[i]: 20 
D/AnswerView(12078): nameUTF8[i]: 20 
D/AnswerView(12078): nameUTF8[i]: 20 
D/AnswerView(12078): nameUTF8[i]: 20 

显示该文件名的所提取的子的第六个字节,作为以及文件名本身,是“B5”而不是“B6”,因为它在搜索字符串中。但是,打印的文件名正确显示。我很难过。为什么当底层字符不同时,文件名正确显示给控制台?为什么在文件名的开头还有另外3个非空白字节 - 在搜索字符串中不需要某种方式来表示“ぶ”字符?

回答

2

该问题看起来是规范化形式之一。例如,我知道在Mac上,文件系统始终处于NFD状态。但是您发布的字符串是NFC。观看:

% cat /tmp/u 
呼ぶ 

% uwc /tmp/u 
    Paras Lines Words Graphs Chars Bytes File 
     0  1  1  3  3  7 /tmp/u 

% uniquote -v /tmp/u 
\N{CJK UNIFIED IDEOGRAPH-547C}\N{HIRAGANA LETTER BU} 

% nfd /tmp/u | uniquote -v 
\N{CJK UNIFIED IDEOGRAPH-547C}\N{HIRAGANA LETTER HU}\N{COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK} 

% nfc /tmp/u | uniquote -v 
\N{CJK UNIFIED IDEOGRAPH-547C}\N{HIRAGANA LETTER BU} 

所以我认为你将不得不考虑转换为NFD。

BTW,即U + 547C CJK代码点恰好是这起永硕联合数据库:

呼 U+547C Lo Han CJK UNIFIED IDEOGRAPH-547C 
    Mandarin  hu1 xu1 
    Cantonese fu1 
    JapaneseKun yobu 
    JapaneseOn ko 
    Korean  ho 
    HanyuPinlu hu1(378) hu5(107) 
    Vietnamese hô 
+0

这解释了这个问题。由于额外的三个字节,文件名必须在NFD中,这将是将“ふ”转换为“ぶ”的额外的波形。我找到了一个解释这个的链接,以及Java中的解决方案(使用Normalizer),非常好:http://weblogs.java.net/blog/joconner/archive/2007/02/normalization_c.html – 2011-04-28 03:36:37

0
String compareStart = name.substring(0, string1.length()); 

这里使用的是从string1采取的长度切name。正如汤姆指出的那样,这些字符串有不同的归一化形式,所以它们的长度不需要重合。