Genel bir çözüm arayanlar için bunlar ortak kriterler olabilir:
- Dosya adı dizeye benzemelidir.
- Kodlama, mümkün olduğunda tersine çevrilebilir olmalıdır.
- Çarpışma olasılığı en aza indirilmelidir.
Bunu başarmak için, kural dışı karakterleri eşleştirmek, bunları yüzde olarak kodlamak ve ardından kodlanmış dizenin uzunluğunu sınırlamak için regex kullanabiliriz .
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);
}
desenler
Yukarıdaki model , POSIX spesifikasyonunda izin verilen karakterlerin muhafazakar bir alt kümesine dayanmaktadır .
Nokta karakterine izin vermek istiyorsanız, şunu kullanın:
private static final Pattern PATTERN = Pattern.compile("[^A-Za-z0-9_\\-\\.]");
"" Gibi dizelere karşı dikkatli olun. ve ".."
Büyük / küçük harfe duyarlı olmayan dosya sistemlerinde çarpışmaları önlemek istiyorsanız, büyük harflerden kaçmanız gerekir:
private static final Pattern PATTERN = Pattern.compile("[^a-z0-9_\\-]");
Veya küçük harflerden kaçının:
private static final Pattern PATTERN = Pattern.compile("[^A-Z0-9_\\-]");
Beyaz liste kullanmak yerine, belirli dosya sisteminiz için ayrılmış karakterleri kara listeye almayı seçebilirsiniz. EG Bu normal ifade FAT32 dosya sistemlerine uygundur:
private static final Pattern PATTERN = Pattern.compile("[%\\.\"\\*/:<>\\?\\\\\\|\\+,\\.;=\\[\\]]");
uzunluk
Android'de güvenli sınır 127 karakterdir . Çoğu dosya sistemi 255 karaktere izin verir.
İpinizin başı yerine kuyruğu tutmayı tercih ediyorsanız, şunu kullanın:
// Truncate the string.
int start = Math.max(0,encoded.length()-MAX_LENGTH);
return encoded.substring(start,encoded.length());
Decoding
Dosya adını tekrar orijinal dizeye dönüştürmek için şunu kullanın:
URLDecoder.decode(filename, "UTF-8");
Sınırlamalar
Daha uzun dizeler kesildiği için, kodlama sırasında ad çakışması veya kod çözme sırasında bozulma olasılığı vardır.