我有一个接收上传文本文件的网络服务。所以在服务器端,我得到了一个InputStream对象,我尝试将它包装为一个InputStreamReader,并以“UTF8”作为字符集。但我注意到,当我上传以 US-ASCII 编码的文件时也可以工作。似乎 Java 可以自动将文件从所有其他字符集转换为 UTF8。我对吗?charset 属性是如何工作的?
5 回答
UTF-8 是 US-ASCII 的超集
ASCII 是 7 位字符(0 到 127),这些在 US-ASCII 和 UTF-8 以及许多其他字符集中没有变化。大多数字符集不同的地方是高位字节(128 到 255) 在 US-ASCII 的情况下,它是未定义的,对于 ISO-8859-1,这些字符不变,允许最多 255 个字符,在 UTF-8 中,字符是编码为使用 2 到 4 个字节,因此它最多可以表示 0x10FFFF 或 128K 个字符。
为什么?如果您要上传文件,只需使用 InputStream。您不想将文件数据转换为 UTF-16,然后再转换回可能的不同编码。
只需复制字节。
不,Java 通常不会自动将一个字符集转换为另一个字符集,尤其是当您明确告诉它要使用哪个字符集时。
但问题是 UTF-8 与 ASCII 兼容。这意味着每个有效的 ASCII 流也自动成为有效的 UTF-8 流,并且仅包含以 UTF-8 编码的 ASCII 字符的文本也是有效的 ASCII。
因此,如果您打算只接受 ASCII 和 UTF-8 输入,那么将其全部视为 UTF-8 是完全有效的。如果您还计划支持其他编码,那么您将需要某种方式来传输有关正在使用的实际编码的信息。
这仅适用于 US-ASCII 是 UTF-8 的子集(每个 ASCII 文件也是相同数据的有效 UTF-8 文件)。
试试别的,它会坏的。
UTF-8 与 ASCII 兼容,即每个 ASCII 文档也是有效的 UTF-8。引用维基百科:
[UTF-8] 旨在向后兼容 ASCII 并避免 UTF-16 和 UTF-32 中字节顺序和字节顺序标记的复杂性。
[...] Unicode 的前 128 个字符与 ASCII 一对一对应,使用与 ASCII 具有相同二进制值的单个八位字节进行编码,从而使有效的 ASCII 文本也成为有效的 UTF-8 编码的 Unicode。
所以 Java 仍然将您的流视为 UTF-8。如果您尝试使用 UTF-8 阅读器使用 UTF-16 或 UTF-32,您将得到垃圾。