ObjectOutputStream的writeObject方法使用哪种字符编码?

5

我了解到Java在内部使用UTF-16编码。也就是说,如果我有这样的代码:String var = "जनमत"; 那么"जनमत"将会在内部以UTF-16编码形式存储。因此,如果我将这个变量转储到某个文件中,例如下面的代码:

fileOut = new FileOutputStream("output.xyz");
out = new ObjectOutputStream(fileOut);
out.writeObject(var);

在文件“output.xyz”中,“जनमत”字符串的编码是否为UTF-16?另外,如果我想通过ObjectInputStream从文件“output.xyz”读取,我能否得到变量的UTF-16表示形式?

谢谢。


我认为你不应该关心ObjectOutputStream使用的编码方式。如果你将在其他地方使用生成的文件,那就不要使用ObjectOutputStream。如果不是,你也不必考虑它。 - khachik
2
你真的不应该直接在*.java源文件中放置非ASCII字符,这个问题已经被反复讨论过了。基本上,.java文件没有与之关联的元数据来告知它们所编码的编码方式,也没有任何强制规定使用特定编码的规范。因此,当您混合使用操作系统、集成开发环境、文本编辑器、工具(批处理/Shell脚本)等时,问题必然会出现。您应该始终将非ASCII字符外部化到其他文件中(对其编码完全掌控),或者使用Java转义符\uXXXX*。 - SyntaxT3rr0r
回答你的问题,Java内部使用UTF-16或UCS-2(或是小Fearings的月靴颜色)存储字符串与保存该字符串到文件时使用的编码格式无关。 - SyntaxT3rr0r
3个回答

7
如果我将这个变量转储到某个文件中,那么在文件“output.xyz”中,“जनमत”字符串的编码会是UTF-16吗? 您的字符串在文件中的编码将是ObjectOutputStream想要放入的任何格式。您应该将其视为只能由ObjectInputStream读取的黑盒子。(严肃地说——即使格式是经过充分记录的,如果您想使用其他工具读取它,您应该自己将对象序列化为XML或JSON或其他格式。)
以后,如果我想通过ObjectInputStream从文件“output.xyz”中读取,我能否获得该变量的UTF-16表示形式?
如果您使用 ObjectInputStream 读取文件,则会获得原始对象的副本。这将包括一个 java.lang.String,它只是一个字符流(而不是字节)- 如果您愿意,可以通过 getBytes() 方法获取其 UTF-16 表示形式(尽管我怀疑您实际上并不需要)。
总之,不要过于担心序列化的内部细节。如果您需要知道发生了什么,请自己创建文件;如果您只是好奇,相信JVM会做正确的事情。

1

关闭:它不是完全的UTF-16,而是类似于UCS-2;但无论如何,它对大多数字符(和2个字符序列,即某些很少使用的代码点的4个字节序列)都使用2个字节。

ObjectOutputStream使用一种称为修改后的UTF-8的东西,它类似于UTF-8,但其中零字符表示为2字节序列,这在UTF-8中不合法(由于编码的唯一性限制),但这种自然解码回值0。

但你真正想问的是“它是否能够使我写一个字符串,读取一个字符串”——答案是肯定的。JDK在写出字节时进行适当的编码,在读取时进行解码。

就它的价值而言,最好使用“writeUTF()”方法来处理字符串,因为我认为生成的输出更紧凑。但“writeObject()”也可以工作,只需要更多的元数据。


0

补充一点,ObjectOutputStream.writeString() 将确定给定字符串的 UTF 长度,并以 "标准" UTF 或 "长" UTF 格式之一进行编写,在 javadoc 中已经声明过。

"长" UTF 格式与标准 UTF 相同,只是使用 8 字节头(而不是标准的 2 字节)来传达 UTF 编码长度。

我从代码中获得了这个信息...

private void writeString(String str, boolean unshared) throws IOException {
    handles.assign(unshared ? null : str);
    long utflen = bout.getUTFLength(str);
    if (utflen <= 0xFFFF) {
        bout.writeByte(TC_STRING);
        bout.writeUTF(str, utflen);
    } else {
        bout.writeByte(TC_LONGSTRING);
        bout.writeLongUTF(str, utflen);
    }
}

writeObject(Object obj)中,他们进行了一项检查

if (obj instanceof String) {
    writeString((String) obj, unshared);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接