最近我遇到了一个麻烦,从Android内部SD卡复制一个文件到可移动SD卡。
这个文件有一个特殊字符"snake"(http://www.fileformat.info/info/unicode/char/1f40d/index.htm)。
可以保存到内置SD卡。但它不能复制到可移动SD卡。我试图从我的电脑复制到可移动SD卡。但也失败了。
所以我创建了一个代码来改变特殊字符
for(int i =0; i < input.length(); i++) {
if(input.codePointAt(i) > 0xFFFF) { //check is it special character?
//change string!!!!!
i ++;
} else {
builder.append(input.charAt(i));
}
}
它工作,所以我可以解决我的问题。但是我想知道
的原因为什么我不能复制到可移动SD卡,它有一个特殊的字符(unicode 10000超过像U+1f40d)。
最新(可能是最终)答案:
最近我用android手机(Jellybean)格式化了一张SD卡,只是为了检查新格式化的文件系统。结果是FAT
系统。
FAT
systems (任意版本)不支持UTF-16
长文件名。只支持UCS-2
长文件名。(前者支持代理对,而后者不支持)
从第二个链接:
…而UCS-2则仅限于BMP字符。这些编码是实用的,因为单位长度是字符数。
这可以解释你的设备上的"Snake"字符问题。您能帮我们确认文件系统吗?
你的内部文件系统,另一方面,将取决于制造商。检查第四个链接,它确认了这一点。
-
UTF-16 vs UCS-2
Unicode编码 维基百科FAT文件系统链接
Android内部文件系统
之前回答(2):
我试图在我的PC上复制这个场景,在源文件名中使用'Snake' Unicode,并使用Files
类进行复制,并且成功复制了。
代码:
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
public class abc {
/**
* @param arg
* @throws IOException
*/
public static void main(String arg[]) throws IOException {
StringBuffer sb = new StringBuffer();
sb.appendCodePoint(128013);
File tmpFile = File.createTempFile("testFile" + sb.toString(), ".txt");
File dirTrgt = new File("C:\"+tmpFile.getName());
Files.copy(tmpFile.toPath(), dirTrgt.toPath(), StandardCopyOption.REPLACE_EXISTING);
tmpFile.deleteOnExit();
}
}
上一个答案(1):
有效码位范围为U+0000至U+10FFFF。
在Java中,char
有严格的长度为2字节-> 16位-> 0xFFFF(最大值)
值(从#getCodePointAt(int)
得到的int
值)支持所有代码点。(Unicode字符称为码点)
因此,当您遇到字符> 0xFFFF
时,您的input.charAt(i)
(很可能)返回一个溢出的char
,即!= input.getCodePointAt(i)
关于UTF-16:
BMP—BMP (Basic Multilingual Plane)编码范围为U+0000U +飞行符。
超过该范围的任何字符都称为补充字符。这些字符使用
char
值的对表示。补充字符由高代理符——值范围为0xD800至0xDBFF——和低代理符——值范围为0xDC00至0xDFFF——
组成
从你在问题中给出的链接我们可以看到这一点。对于UTF-16, Snake的值:
UTF-16(十六进制)—0xD83D 0xDC0D (d83ddc0d)
更多信息请参考以下链接:
Android Doc for Character Classhow-does-java-store-utf-16-characters-in-its-16-bit-char-type