Использование ContentResolver и Regex для получения музыки из определенной папки

В настоящее время я пытаюсь получить музыкальные файлы в определенной папке из ContentResolver. Мне нужны файлы только в этой папке, а не в подпапке. Я получил эти файлы, выполнив следующие действия:

String pattern = f.getAbsolutePath() + "/[^/]*"; // f is the folder where I want to search
ArrayList<TrackInfo> retVal = new ArrayList<TrackInfo>();
Cursor mCursor = null;

String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0 AND " + DATA + " LIKE '" + f.getAbsolutePath() + "/%'";

Uri contentUri = Media.getContentUriForPath(Environment.getExternalStorageDirectory().getPath());
String projection[] = new String[]{DATA};

mCursor = context.getContentResolver().query(contentUri, projection, selection, null, DATA);

String data, fileName[];
while(mCursor.moveToNext()){

    data = mCursor.getString(0);        
    if(data.matches(pattern)){
        fileName = data.split("/");

        retVal.add(new TrackInfo(fileName[fileName.length-1], null, data, null, -1, R.drawable.notes, false));
    }           
}

mCursor.close();

Это сработало для большинства случаев. Но теперь у меня, кажется, проблема с моей моделью. Проблема в том, что если шаблон содержит круглые скобки, data.matches(pattern) всегда возвращает false. Примеры, которые я пробовал:

String pattern1 = "/mnt/somepath/folder(with-parentheses)/[^/]*";
String pattern2 = "/mnt/somepath/folder/[^/]*";

String string1 = "/mnt/somepath/folder(with-parentheses)/test1";
String string2 = "/mnt/somepath/folder/test2";

System.out.println("\"" + string1 + "\"" + ".matches(\"" + pattern1 + "\") = " + string1.matches(pattern1));
System.out.println("\"" + string2 + "\".matches(\"" + pattern2 + "\") = " + string2.matches(pattern2));

Результат был:

"/mnt/somepath/folder(with-parentheses)/test1*".matches("/mnt/somepath/folder(with-parentheses)/[^/]*") = false
"/mnt/somepath/folder/test2".matches("/mnt/somepath/folder/[^/]*") = true

Теперь у меня вопрос:
Есть ли более эффективный способ получить все музыкальные файлы в папке? - Я уже пытался проверить каждый файл в папке на наличие шаблона (содержащего поддерживаемые форматы мультимедиа, которые я нашел здесь). Проблема с этим подходом заключается в том, что эти форматы являются только базовыми форматами мультимедиа — телефон может поддерживать больше.
И почему мой шаблон не работает?

Большое спасибо.


person MalaKa    schedule 31.12.2013    source источник
comment
Вам нужно избежать (), то есть \(\), так как () являются специальными символами в регулярном выражении.   -  person nhahtdh    schedule 31.12.2013
comment
Спасибо, это сработало. Если вы поместите это в ответ, я приму это.   -  person MalaKa    schedule 31.12.2013


Ответы (1)


(, ) (и многие другие, такие как +,*, [, ], .) являются специальными символами в регулярном выражении. Следовательно, необходимо экранировать их, т. е. \(, \), чтобы указать литеральный символ.

Однако в этом случае, поскольку вы получаете шаблон путем объединения f.getAbsolutePath(), настоятельно рекомендуется использовать Pattern.quote(String), чтобы сделать все символы в f.getAbsolutePath() литеральными. Это гарантирует, что ни один из символов не интерпретируется как специальный символ в регулярном выражении.

String pattern = Pattern.quote(f.getAbsolutePath()) + "/[^/]*";

(Когда вы печатаете pattern после применения Pattern.quote, вы можете заметить, что он добавляет \Q и \E к исходной строке. Это способ избежать всех символов в длинной строке, поддерживаемый регулярными выражениями Java и некоторыми другими вариантами регулярных выражений).

person nhahtdh    schedule 31.12.2013