用于读写文件的正确 Java 类?

问题描述 投票:0回答:1

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

这些是:

  • BufferedReader
    BufferedWriter
  • FileReader
    FileWriter
  • FileInputStream
    FileOutputStream
  • InputStreamReader
    OutputStreamWriter
  • Scanner
    班级

以下哪一个是文本文件管理的最佳替代方案?序列化的最佳替代方案是什么? Java NIO 对此有何评论?

java file serialization file-io text-files
1个回答
20
投票

两种数据

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

  • 二进制数据
  • 文本数据

当它是一个文件(或套接字,或数据库中的 BLOB,或...)时,它始终是二进制数据first

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

二进制数据

每当您想要处理 binary 数据时,您都需要使用

InputStream
/
OutputStream
类(通常,名称中包含
Stream
的所有内容)。

这就是为什么有

FileInputStream
FileOutputStream
:这些 读取和 写入 文件,并且它们处理二进制数据。

文本数据

每当您想要处理 text 数据时,您都需要使用

Reader
/
Writer
类。

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

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

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

为了阅读,我们还应该提到

BufferedReader
,它可以包裹在任何其他
Reader
周围,并增加一次处理整行的能力。

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

缩小差距

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

an
    InputStreamReader
  • 消耗
    a InputStream 并且
    本身就是
    a Reader
    an 
  • OutputStreamWriter
  • Writer 并且
    写入
    OutputStream
    
    
  • 然后还有“快捷课程”,它们基本上结合了其他两个经常组合的课程。

a
    FileReader
  • 基本上是
    FileInputStream
    InputStreamReader
     的组合
    
    a
  • FileWriter
  • 基本上是
    FileOutputStream
    OutputStreamWriter
     的组合
    
  • 请注意,与更复杂的“手工构建”替代方案相比,
FileReader

FileWriter
过去有一个主要缺点:它们使用平台默认编码,这可能不是您想要做的!在 Java 11 中,他们终于有了双参数构造函数,因此在想要提供编码时仍然可以使用它们。
序列化怎么样?

ObjectOutputStream

ObjectInputStream
 是用于序列化的特殊流。
由于类的名称意味着序列化仅涉及二进制数据(即使序列化

String

对象),因此您需要专门使用

*Stream
类。只要您避免任何
Reader
/
Writer
课程,就应该没问题。
更多资源

    基本 I/O 轨迹
  • Joel 关于 Unicode 的旧文章
  • (很好的介绍,技术细节稍微简单)
  • 论平台默认编码的弊端
  • 也是这个
© www.soinside.com 2019 - 2024. All rights reserved.