Đối với những người đang tìm kiếm một giải pháp chung, đây có thể là những tiêu chí chung:
- Tên tệp phải giống với chuỗi.
- Mã hóa phải được đảo ngược nếu có thể.
- Xác suất va chạm nên được giảm thiểu.
Để đạt được điều này, chúng ta có thể sử dụng regex để khớp các ký tự không hợp lệ, mã hóa phần trăm chúng, sau đó giới hạn độ dài của chuỗi mã hóa.
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);
}
Hoa văn
Mẫu trên dựa trên một tập hợp con bảo toàn các ký tự được phép trong thông số POSIX .
Nếu bạn muốn cho phép ký tự dấu chấm, hãy sử dụng:
private static final Pattern PATTERN = Pattern.compile("[^A-Za-z0-9_\\-\\.]");
Chỉ cần cảnh giác với các chuỗi như "." và ".."
Nếu bạn muốn tránh va chạm trên các hệ thống tệp không phân biệt chữ hoa chữ thường, bạn sẽ cần phải thoát các chữ hoa:
private static final Pattern PATTERN = Pattern.compile("[^a-z0-9_\\-]");
Hoặc thoát các chữ cái thường:
private static final Pattern PATTERN = Pattern.compile("[^A-Z0-9_\\-]");
Thay vì sử dụng danh sách trắng, bạn có thể chọn đưa vào danh sách đen các ký tự dành riêng cho hệ thống tệp cụ thể của mình. EG Regex này phù hợp với hệ thống tệp FAT32:
private static final Pattern PATTERN = Pattern.compile("[%\\.\"\\*/:<>\\?\\\\\\|\\+,\\.;=\\[\\]]");
Chiều dài
Trên Android, 127 ký tự là giới hạn an toàn. Nhiều hệ thống tệp cho phép 255 ký tự.
Nếu bạn muốn giữ lại phần đuôi thay vì phần đầu của chuỗi, hãy sử dụng:
// Truncate the string.
int start = Math.max(0,encoded.length()-MAX_LENGTH);
return encoded.substring(start,encoded.length());
Giải mã
Để chuyển đổi tên tệp trở lại chuỗi ban đầu, hãy sử dụng:
URLDecoder.decode(filename, "UTF-8");
Hạn chế
Bởi vì các chuỗi dài hơn bị cắt ngắn, có khả năng xảy ra xung đột tên khi mã hóa hoặc hỏng khi giải mã.