Dla tych, którzy szukają ogólnego rozwiązania, mogą to być typowe kryteria:
- Nazwa pliku powinna przypominać ciąg.
- W miarę możliwości kodowanie powinno być odwracalne.
- Należy zminimalizować prawdopodobieństwo kolizji.
Aby to osiągnąć, możemy użyć wyrażenia regularnego, aby dopasować niedozwolone znaki, zakodować je procentowo , a następnie ograniczyć długość zakodowanego ciągu.
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);
}
Wzory
Powyższy wzorzec jest oparty na konserwatywnym podzbiorze dozwolonych znaków w specyfikacji POSIX .
Jeśli chcesz zezwolić na znak kropki, użyj:
private static final Pattern PATTERN = Pattern.compile("[^A-Za-z0-9_\\-\\.]");
Uważaj tylko na ciągi typu „”. i ".."
Jeśli chcesz uniknąć kolizji w systemach plików bez rozróżniania wielkości liter, musisz uciec z wielkich liter:
private static final Pattern PATTERN = Pattern.compile("[^a-z0-9_\\-]");
Lub unikaj małych liter:
private static final Pattern PATTERN = Pattern.compile("[^A-Z0-9_\\-]");
Zamiast używać białej listy, możesz zdecydować się na czarną listę znaków zastrzeżonych dla swojego konkretnego systemu plików. EG To wyrażenie regularne pasuje do systemów plików FAT32:
private static final Pattern PATTERN = Pattern.compile("[%\\.\"\\*/:<>\\?\\\\\\|\\+,\\.;=\\[\\]]");
Długość
W systemie Android bezpieczny limit to 127 znaków . Wiele systemów plików dopuszcza 255 znaków.
Jeśli wolisz zachować ogon zamiast główki sznurka, użyj:
// Truncate the string.
int start = Math.max(0,encoded.length()-MAX_LENGTH);
return encoded.substring(start,encoded.length());
Rozszyfrowanie
Aby przekonwertować nazwę pliku z powrotem na oryginalny ciąg, użyj:
URLDecoder.decode(filename, "UTF-8");
Ograniczenia
Ponieważ dłuższe łańcuchy są obcinane, istnieje możliwość kolizji nazw podczas kodowania lub uszkodzenia podczas dekodowania.