首页 > 解决方案 > Java:Sytem.out/in/err 文件使用哪些隐式编码?

问题描述

第一个任务:我想从 System.in 读入阅读器。似乎这是通过

InputStreamReader cin = new InputStreamReader(System.in);

那么还有其他构造函数,包括编码。目前尚不清楚默认编码是什么。据我了解, System.in 只是一个字节流。而 InputStreamReader 读取字符。但是 InputStream 的构造函数在哪里知道字符集?我必须应用特定的字符集吗?如果是这样,或者我必须离开它吗?

根据有关 System.out 和 System.err 的问题。两者似乎都是打印流,尤其是读取字节。

OutputStreamWriter out  = new OutputStreamWriter(System.out);

好的选择正确的编码还是我必须使用不同的构造函数?

System.err 呢?

还有什么字符集????

我对 PipedReader/Writer 有同样的问题。至少他们必须重合,对吧?

对于 StringWriter/Reader:与字符串相同的编码,即 utf8,对吗?

关于文件的最后一个问题。FileReader/Writer 是 InputStreamReader/Writer 的子类。这似乎是合理的,因为文件是一个字节序列。但与 InputStreamReader/Writer 的构造函数不同,后者具有带字符集的构造函数,FileReader/Writer 没有。他们怎么知道文件的编码???

感谢您的澄清。

标签: javaencodingcharset

解决方案


我想从 System.in 读入阅读器...通过
InputStreamReader cin = new InputStreamReader(System.in);
目前尚不清楚默认编码是什么。据我了解, System.in 只是一个字节流。而 InputStreamReader 读取字符。但是 InputStream 的构造函数在哪里知道字符集?

一个可能想了解 Java 标准库元素的人可以想象查看文档,即那个 ctor 的 Javadoc,它说

创建一个使用默认字符集的 InputStreamReader。

在旧版本中,这实际上是一个超链接,但不再是。然而,页面顶部的文字描述了整个课程

InputStreamReader 是从字节流到字符流的桥梁:它读取字节并使用指定的字符集将它们解码为字符。它使用的字符集可以由名称指定,也可以显式给出,或者可以接受平台的默认字符集。

并且字符集确实超链接java.nio.charset.Charset

Java 虚拟机的每个实例都有一个默认字符集,它可能是也可能不是标准字符集之一。默认字符集在虚拟机启动期间确定,通常取决于底层操作系统使用的语言环境和字符集。

并记录一个您可以调用以找出该默认值的方法。

我必须应用特定的字符集吗?如果是这样,或者我必须离开它吗?

取决于您将要读取的数据。如果 Java 使用来自“终端”(在 Unix 中)或“控制台”(在 Windows 中)的标准输入运行,通常用户输入将匹配操作系统中设置的语言环境(或 Windows 代码页),如上所述为 Java 默认值,所以你可以使用默认值。如果输入将从文件中重定向(或者在 Unix 上是一个“heredoc”,它实际上是一个临时文件),它取决于文件中的内容;如果输入将从另一个程序的管道重定向(在某些 Unix shell 上,包括进程替换),这取决于其他程序输出的内容——如果它在同一系统中运行,则可能(但不确定)正在使用与为 Java 进程设置的语言环境相同。

根据有关 System.out 和 System.err 的问题。两者似乎都是打印流,尤其是读取字节。

(除此之外:“according”在那里不符合语法。您可以说“[the/a]相应的问题”,但只是“[the] same question”是正确且更清晰的。)

是的,这里是(或子类)JavadocSystem.out .err的实例,这是一种特殊情况和一种混合;它处理写入(不读取)字节的方式与任何其他字节相同,但也具有与. 实际将输出格式化(如有必要)为字符,并(通常)将它们传递给将字符编码为字节并传递给底层流,但同时进行格式化和编码本身,直接输出字节。查看 ctor 列表,您可以看到您可以指定字符集名称或对象,也可以使用默认值;使用默认值的实现。PrintStreamOutputStreamprint*printf/formatPrintWriterPrintWriterOutputStreamWriterPrintStreamSystem.out .err

OutputStreamWriter如果您确实在这些(的流部分)上创建自己PrintStream的,您可以指定任何字符集或使用默认值——尽管如果您要使用默认值,为什么不直接使用PrintStream

还有什么字符集????

如果您的意思是这个概念,请参阅我上面链接的类文档。如果您的意思是给定 JVM 上可用的特定字符集,那可能会有所不同。availableCharsets()您可以使用该类中的静态方法在某个时间点获取当前列表。

我对 PipedReader/Writer 有同样的问题。至少他们必须重合,对吧?
对于 StringWriter/Reader:与字符串相同的编码,即 utf8,对吗?

这些是不同的。它们不能以字节为单位工作,至少不可见。

首先String,JavaString被定义为由 16 位组成char,而不是字节。最初,当 Unicode 也是 16 位时,这些是真正的字符(现在称为 UCS-2)。当 Unicode 超过 16 位但 Java 无法轻易更改时,这些成为 UTF-16 代码元素,它们主要是字符,但一组称为代理项,成对使用来表示“补充”字符。最新版本的 Java(9 以上,IIRC)实际上 String数据存储为单个字节,当且仅当所有 UTF-16 代码元素都适合一个字节,这相当于它们在 ISO-8859-1(Latin-1)中字符集。但这纯粹是内部的;API 仍然接受并返回char char[]等等。因此,没有完成 NIO/Charset 模型所设想的类型的编码和解码,并且不涉及任何字符集。

Piped{Input,Output}Stream虽然也存在面向字节的,Piped{Reader,Writer}但不要使用它们;相反,它们只是存储在char写入端提供的序列并在读取端返回它们。同样没有进行编码或解码,也没有涉及任何字符集。

关于文件的最后一个问题。FileReader/Writer 是 InputStreamReader/Writer 的子类。这似乎是合理的,因为文件是一个字节序列。但与 InputStreamReader/Writer 的构造函数不同,后者具有带字符集的构造函数,FileReader/Writer 没有。他们怎么知道文件的编码???

(编辑)从 Java 11 起不再适用;现在他们确实有带有字符集的 ctor,并且没有指定字符集的 ctor 被记录为使用默认字符集;请参阅FileReaderFileWriter。需要明确的是,Reader 不知道文件内容的实际编码(假设有一些),它只知道您说要使用的内容或默认值;如果这与实际文件内容不匹配,您可能会获得部分或全部垃圾数据。Writer 确实会写入您指定或默认的编码,因此内容(或至少附加时的内容)将采用该编码。11点前,班级 总结说“这个类的构造函数假定默认的字符编码和默认的字节缓冲区大小是合适的。”


推荐阅读