10

阅读一些关于 Java 文件 I/O 管理的资料后,我了解到输入和输出操作有不止一种选择。

这些是:

  • BufferedReaderBufferedWriter
  • FileReaderFileWriter
  • FileInputStreamFileOutputStream
  • InputStreamReaderOutputStreamWriter
  • Scanner班级

其中哪些是管理文本文件的最佳选择?序列化的最佳选择是什么?Java NIO 对此有何评论?

4

1 回答 1

20

两种数据

一般来说,有两个“世界”:

  • 二进制数据
  • 文本数据

当它是文件(或套接字,或数据库中的 BLOB,或...)时,它总是首先是二进制数据。

其中一些二进制数据可以被视为文本数据(其中涉及称为“编码”或“字符编码”的东西)。

二进制数据

每当您想处理二进制数据时,您都需要使用InputStream/类(通常是其名称OutputStream中包含的所有内容)。Stream

这就是为什么有 aFileInputStream和 a FileOutputStream:它们读取写入文件并处理二进制数据。

文本数据

每当您要处理文本数据时,都需要使用Reader/Writer类。

每当您需要将二进制数据转换为文本(反之亦然)时,您就需要某种编码(常见的有 UTF-8、UTF-16、ISO-8859-1(和相关的)和旧的 US- ASCII)。“幸运的是”Java 平台还有一种叫做“默认平台编码”的东西,只要它需要它就会使用它,但代码没有指定它。

平台默认编码是一把双刃剑,但是:

  • 它使编写代码更容易,因为您不必为每个操作指定编码,
  • 它可能与您拥有的数据不匹配:如果平台默认编码是 ISO-8859-1 并且您读取的文件实际上是 UTF-8,那么您将得到一个加扰的输出!

对于阅读,我们还应该提到BufferedReaderwhich 可以包裹任何其他内容Reader并增加一次处理整行的能力。

Scanner是一个特殊的类,用于将文本输入解析为标记。它对结构化文本最有用,但通常用于System.in提供一种非常简单的方式来从标准输入读取数据(即从用户在键盘上输入的内容)。

弥合差距

现在,令人困惑的是,有些类在这些世界之间架起了一座桥梁,它们的名称通常包含两个部分

  • anInputStreamReader 消耗aInputStream并且本身就是a Reader
  • anOutputStreamWriter 是 a Writer写入a OutputStream

然后是“快捷类”,它们基本上结合了其他两个经常组合的类。

  • aFileReader基本上是 aFileInputStream和 an的组合InputStreamReader
  • aFileWriter基本上是 aFileOutputStream和 an的组合OutputStreamWriter

请注意,FileReaderFileWriter更复杂的“手工构建”替代方案相比,它们有一个主要缺点:它们始终使用平台默认编码,这可能不是您想要做的!

序列化呢?

ObjectOutputStream并且ObjectInputStream是用于序列化的特殊流。

由于类的名称暗示序列化只涉及二进制数据(即使序列化String对象),所以您将希望*Stream专门使用类。只要你避免任何Reader/Writer类,你应该没问题。

更多资源

于 2013-10-17T14:55:59.697 回答