为什么不能在SD卡中使用特殊字符(超过10000个unicode)文件名



最近我遇到了一个麻烦,从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"字符问题。您能帮我们确认文件系统吗?

你的内部文件系统,另一方面,将取决于制造商。检查第四个链接,它确认了这一点。

  1. UTF-16 vs UCS-2

  2. Unicode编码
  3. 维基百科FAT文件系统链接

  4. 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 Class

how-does-java-store-utf-16-characters-in-its-16-bit-char-type

最新更新