Java读取文件不同的方法

2022-09-04 19:54:53

似乎有很多很多方法可以在Java中读取文本文件(等)。我个人最喜欢的是使用一个 in 构造函数(它只是更简单,更好地处理数学数据,并且具有熟悉的语法)。BufferedReaderDataInputStreamScannerFile

蜘蛛鲍里斯也提到和.ChannelRandomAccessFile

有人可以解释这些方法的优缺点吗?具体来说,我想什么时候使用每种方法?

(编辑)我认为我应该具体一点,并补充说我对这种方法有强烈的偏好。所以真正的问题是,我什么时候不想使用它?Scanner


答案 1

让我们从头开始。问题是你想做什么?

了解文件的实际含义非常重要。文件是光盘上的字节集合,这些字节是您的数据。Java在上面提供了各种抽象级别:

  1. File(Input|Output)Stream- 将这些字节读取为 .byte
  2. File(Reader|Writer)- 从字节流读取为 .char
  3. Scanner- 从流中读取并标记它。char
  4. RandomAccessFile- 将这些字节读取为可搜索的.byte[]
  5. FileChannel- 以安全的多线程方式读取这些字节。

在每个装饰之上,例如,您可以使用 添加缓冲。您可以将换行符感知添加到 with .您可以将 a 转换为 带有 a(目前为 a 指定字符编码的唯一方法)。BufferedXXXFileWriterPrintWriterInputStreamReaderInputStreamReaderReader

那么 - 我什么时候不想使用它[扫描仪]?

如果你愿意,你不会使用 a(这些是一些例子):Scanner

  1. 以 s 的形式读取数据byte
  2. 在序列化的 Java 对象中读取
  3. 将 s 从一个文件复制到另一个文件,可能进行一些过滤。byte

构造函数采用并打开一个具有平台默认编码的也毫无价值 - 这几乎总是一个主意。人们普遍认为,您应该显式指定编码,以避免令人讨厌的基于编码的错误。此外,流不会缓冲。Scanner(File file)FileFileInputStream

所以你可能更好

try (final Scanner scanner = new Scanner(new BufferedInputStream(new FileInputStream())), "UTF-8") {
    //do stuff
}

丑陋,我知道。

值得注意的是,Java 7 提供了进一步的抽象层,以消除循环访问文件的需要 - 这些在 Files 类中:

byte[] Files.readAllBytes(Path path)
List<String> Files.readAllLines(Path path, Charset cs)

这两种方法都将整个文件读取到内存中,这可能不合适。在Java 8中,通过添加对新API的支持,这一点得到了进一步的改进:Stream

Stream<String> Files.lines(Path path, Charset cs)
Stream<Path> Files.list(Path dir)

例如,要从 中获取单词,您可以执行以下操作:Path

    final Stream<String> words = Files.lines(Paths.get("myFile.txt")).
            flatMap((in) -> Arrays.stream(in.split("\\b")));

答案 2

SCANNER:

可以使用正则表达式解析基元类型和字符串。扫描仪使用分隔符模式将其输入分解为标记,默认情况下,分隔符模式与空格匹配。然后,生成的标记可以转换为不同类型的值。可以在 http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html

DATA INPUT STREAM:

允许应用程序以独立于计算机的方式从基础输入流中读取基元数据类型。应用程序使用数据输出流来写入数据,以后可由数据输入流读取。DataInputStream 对于多线程访问不一定是安全的。线程安全是可选的,并且是此类中方法的用户的责任。更多内容可在 http://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html

BufferedReader:

从字符输入流中读取文本,缓冲字符,以便有效地读取字符、数组和行。可以指定缓冲区大小,也可以使用默认大小。默认值足以满足大多数用途。通常,对 Reader 发出的每个读取请求都会导致对基础字符或字节流发出相应的读取请求。因此,建议将 BufferedReader 包装在任何读取() 操作可能代价高昂的读取器上,例如 FileReaders 和 InputStreamReaders。例如

BufferedReader in   = new BufferedReader(new FileReader("foo.in"));

将缓冲指定文件中的输入。如果没有缓冲,每次调用 read() 或 readLine() 都可能导致从文件中读取字节,转换为字符,然后返回,这可能非常低效。通过将每个 DataInputStream 替换为适当的 BufferedReader,可以对使用 DataInputStream 进行文本输入的程序进行本地化。有关详细信息,请参阅 http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html