Java中的字符是1字节还是2字节?

我认为java中的字符是16位,如java doc中所建议的那样。 字符串不是这样吗? 我有一个代码将对象存储到文件中:

public static void storeNormalObj(File outFile, Object obj) { FileOutputStream fos = null; ObjectOutputStream oos = null; try { fos = new FileOutputStream(outFile); oos = new ObjectOutputStream(fos); oos.writeObject(obj); oos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { oos.close(); try { fos.close(); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } } 

基本上,我试图将一个字符串"abcd"存储到文件"output" ,当我用编辑器打开output并删除无字符串部分时,剩下的只是字符串“abcd”,总共是4个字节。 谁知道为什么? 对于ASCII支持的字符串,java是否使用ASCII而不是UNICODE自动节省空间? 谢谢

(我认为“无字符串部分”是指ObjectOutputStream在创建时发出的字节。您可能不想使用ObjectOutputStream,但我不知道您的要求。)

仅供参考,Unicode和UTF-8不是一回事。 Unicode是一种标准,除其他外,指定可用的字符。 UTF-8是一种字符编码,用于指定这些字符在1和0中的物理编码方式。 UTF-8可以使用1个字节表示ASCII(<= 127),最多4个字节表示其他Unicode字符。

UTF-8是ASCII的严格超集。 因此,即使您为文件指定UTF-8编码并向其写入“abcd”,它也只包含这四个字节:它们在ASCII中具有与UTF-8中相同的物理编码。

您的方法使用ObjectOutputStream ,它实际上具有与ASCII或UTF-8明显不同的编码! 如果仔细阅读Javadoc,如果obj是一个字符串并且已经在流中发生,则后续对writeObject调用将导致对前一个字符串的引用被发出,这可能导致在重复字符串的情况下写入更少的字节。

如果您认真理解这一点,那么您真的应该花大量时间阅读有关Unicode和字符编码系统的知识。 维基百科有一篇关于Unicode的优秀文章作为开端。

是的, char在Java运行时环境的上下文中只是Unicode。 如果您希望使用16位编码编写它,请使用FileWriter

  FileWriter outputStream = null; try { outputStream = new FileWriter("myfilename.dat"); int c; while ((c = inputStream.read()) != -1) { outputStream.write(c); } } finally { if (outputStream != null) { outputStream.close(); } } 

如果你看一下String的来源,它会注意到它调用DataOutput.writeUTF来编写字符串。 如果你读到它,你会发现它们被写成“修改过的UTF-8”。 细节很冗长,但如果你不使用非7位ascii,是的,它将需要一个字节。 如果你想要gory细节请查看DataOutput.writeUTF()中的EXTREMELY long javadoc

您可能有兴趣知道Java Update 21性能版本及更高版本中存在-XX:+UseCompressedStrings选项。 这将允许String对不需要char[]字符串使用byte[] char[]

尽管Java Hotspot VM Options指南建议默认情况下它可能已启用,但这可能仅适用于性能版本。 如果我明确地打开它,它似乎对我有用。

那么你期望一个16*4=64 bits = 8 bytes文件? 超过UTF-8或ASCII编码。 将文件写入文件后。 内存(就空间而言)管理取决于操作系统。 而且你的代码没有控制权。