Android, проблема с сопоставлением имени файла в японских символах - PullRequest
2 голосов
/ 26 апреля 2011

Я пытаюсь сопоставить строку поиска с именем файла с рекурсивным поиском в каталоге в Android. Проблема в том, что символы японские, и в некоторых случаях они не совпадают. Например, строка поиска, с которой я пытаюсь сопоставить начало имени файла, это «呼 ぶ». Когда я печатаю имена файлов из file.getName (), это точно отражается, например, имя файла, выводимое на консоль, начинается с «呼 ぶ». Но когда я сопоставляю строку поиска, например, fileName.startwith («呼 ぶ»), не соответствует.

Оказывается, что когда я печатаю подстроку искомого имени файла, второй символ отличается - слово «呼 ふ» вместо «呼 ぶ». Если я извлекаю байты и печатаю шестнадцатеричные символы, последний байт отключается на 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 ]

2 голосов
/ 27 апреля 2011

Проблема выглядит как одна из форм нормализации. Я знаю, что на 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.

Кстати, эта кодовая точка U + 547C CJK происходит из базы данных Unihan:

 呼 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 голосов
/ 28 апреля 2011
String compareStart = name.substring(0, string1.length() );

Здесь вы используете длину, взятую из string1 для нарезки name. Как отметил Том, строки находятся в разных формах нормализации, поэтому их длина не должна совпадать.

...