Для тих, хто шукає загального рішення, це можуть бути звичайні критери:
- Ім'я файлу має нагадувати рядок.
- Кодування повинно бути зворотним, де це можливо.
- Імовірність зіткнень повинна бути зведена до мінімуму.
Щоб досягти цього, ми можемо використовувати регулярний вираз, щоб відповідати незаконним символам, відсотковим кодувати їх, а потім обмежувати довжину кодованого рядка.
private static final Pattern PATTERN = Pattern.compile("[^A-Za-z0-9_\\-]");
private static final int MAX_LENGTH = 127;
public static String escapeStringAsFilename(String in){
StringBuffer sb = new StringBuffer();
// Apply the regex.
Matcher m = PATTERN.matcher(in);
while (m.find()) {
// Convert matched character to percent-encoded.
String replacement = "%"+Integer.toHexString(m.group().charAt(0)).toUpperCase();
m.appendReplacement(sb,replacement);
}
m.appendTail(sb);
String encoded = sb.toString();
// Truncate the string.
int end = Math.min(encoded.length(),MAX_LENGTH);
return encoded.substring(0,end);
}
Візерунки
Наведений вище шаблон заснований на консервативному наборі дозволених символів у специфікації POSIX .
Якщо ви хочете дозволити символ крапки, скористайтеся:
private static final Pattern PATTERN = Pattern.compile("[^A-Za-z0-9_\\-\\.]");
Просто будьте обережні до струн типу "". і ".."
Якщо ви хочете уникнути зіткнень у файлових системах, нечутливих до регістру, вам потрібно буде уникнути великих літер:
private static final Pattern PATTERN = Pattern.compile("[^a-z0-9_\\-]");
Або уникайте малих літер:
private static final Pattern PATTERN = Pattern.compile("[^A-Z0-9_\\-]");
Замість того, щоб використовувати білий список, ви можете вибрати чорний список зарезервованих символів для вашої конкретної файлової системи. EG Цей регекс підходить для файлових систем FAT32:
private static final Pattern PATTERN = Pattern.compile("[%\\.\"\\*/:<>\\?\\\\\\|\\+,\\.;=\\[\\]]");
Довжина
На Android 127 безпечних меж - 127 символів . У багатьох файлових системах розміщено 255 символів.
Якщо ви віддаєте перевагу утримувати хвіст, а не голову своєї струни, використовуйте:
// Truncate the string.
int start = Math.max(0,encoded.length()-MAX_LENGTH);
return encoded.substring(start,encoded.length());
Розшифровка
Щоб перетворити ім'я файлу в початковий рядок, використовуйте:
URLDecoder.decode(filename, "UTF-8");
Обмеження
Оскільки довші рядки усічені, існує можливість зіткнення імен при кодуванні або пошкодження при розшифровці.