Per coloro che cercano una soluzione generale, questi potrebbero essere criteri comuni:
- Il nome del file dovrebbe assomigliare alla stringa.
- La codifica dovrebbe essere reversibile ove possibile.
- La probabilità di collisioni dovrebbe essere ridotta al minimo.
Per ottenere ciò, possiamo usare regex per abbinare caratteri illegali, codificarli in percentuale , quindi limitare la lunghezza della stringa codificata.
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);
}
Patterns
Il modello sopra si basa su un sottoinsieme conservativo di caratteri consentiti nelle specifiche POSIX .
Se vuoi consentire il carattere punto, usa:
private static final Pattern PATTERN = Pattern.compile("[^A-Za-z0-9_\\-\\.]");
Fai solo attenzione alle stringhe come "." e ".."
Se vuoi evitare collisioni su filesystem senza distinzione tra maiuscole e minuscole, dovrai evitare le maiuscole:
private static final Pattern PATTERN = Pattern.compile("[^a-z0-9_\\-]");
Oppure esci dalle lettere minuscole:
private static final Pattern PATTERN = Pattern.compile("[^A-Z0-9_\\-]");
Invece di utilizzare una whitelist, puoi scegliere di inserire nella blacklist i caratteri riservati per il tuo file system specifico. EG Questa regex si adatta ai filesystem FAT32:
private static final Pattern PATTERN = Pattern.compile("[%\\.\"\\*/:<>\\?\\\\\\|\\+,\\.;=\\[\\]]");
Lunghezza
Su Android, 127 caratteri è il limite sicuro. Molti filesystem consentono 255 caratteri.
Se preferisci mantenere la coda, piuttosto che l'estremità della corda, usa:
// Truncate the string.
int start = Math.max(0,encoded.length()-MAX_LENGTH);
return encoded.substring(start,encoded.length());
decodifica
Per riconvertire il nome del file nella stringa originale, utilizzare:
URLDecoder.decode(filename, "UTF-8");
limitazioni
Poiché le stringhe più lunghe vengono troncate, esiste la possibilità di un conflitto di nomi durante la codifica o di un danneggiamento durante la decodifica.