ZetCode

在 Java 中读取文本文件

最后修改日期:2024 年 7 月 10 日

在 Java 中读取文本文件教程中,我们将展示如何在 Java 中读取文本文件。我们使用内置工具,包括 FileReaderInputStreamReaderScanner

以下示例使用此文本文件。

src/main/resources/thermopylae.txt
The Battle of Thermopylae was fought between an alliance of Greek city-states, 
led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the 
course of three days, during the second Persian invasion of Greece. 

该文件位于 src/main/resources/ 目录中。

Java 读取文本类

我们可以使用以下 Java 类在 Java 中读取文本文件。

使用 FileReader 读取文本文件

FileReader 是用于读取字符文件的类。它使用默认缓冲区大小从字符文件中读取文本。从字节到字符的解码使用指定的字符集或平台的默认字符集。

注意: 过去,FileReader 依赖于平台默认的编码。自 Java 11 以来,该问题已得到纠正。现在可以显式指定编码。

Main.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";

    try (BufferedReader br = new BufferedReader(
            new FileReader(fileName, StandardCharsets.UTF_8))) {

        var sb = new StringBuilder();

        String line;
        while ((line = br.readLine()) != null) {

            sb.append(line);
            sb.append(System.lineSeparator());
        }

        System.out.println(sb);
    }
}

此代码示例从 thermopylae.txt 文件中读取文本。

var fileName = "src/main/resources/thermopylae.txt";

fileName 变量中,我们存储文件的路径。

try (BufferedReader br = new BufferedReader(
    new FileReader(fileName, StandardCharsets.UTF_8))) {

FileReader 将文件名作为第一个参数。第二个参数是使用的字符集。FileReader 被传递给 BufferedReader,后者缓冲读取操作以获得更好的性能。这是一个 try-with-resources 语句,它确保资源(缓冲读取器)在语句末尾被关闭。

var sb = new StringBuilder();

String line;
while ((line = br.readLine()) != null) {

    sb.append(line);
    sb.append(System.lineSeparator());
}

System.out.println(sb);

将行打印到控制台会消耗额外的资源。因此,我们使用 StringBuilder 来构建输出字符串并一次性打印它。这是一个可选的优化。System.lineSeparator 返回系统相关的行分隔符字符串。

使用 Files.readAllLines 读取文本文件

Files.readAllLines 方法读取文件中的所有行。此方法确保在读取所有字节或抛出异常时关闭文件。文件中的字节使用指定的字符集解码为字符。

请注意,此方法将整个文件读取到内存中;因此,它可能不适用于非常大的文件。

Main.java
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";

    List<String> lines = Files.readAllLines(Paths.get(fileName),
            StandardCharsets.UTF_8);

    for (String line : lines) {

        System.out.println(line);
    }
}

使用 Files.readAllLines 方法读取 thermopylae.txt 文件的内容并将其打印到控制台。

使用流式 API 读取文本文件

读取文本文件的另一种选择是使用 Java 流式 API。Files.lines 将文件中的所有行作为流读取。文件中的字节使用 StandardCharsets.UTF-8 字符集解码为字符。

Main.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";

    var path = Paths.get(fileName);

    try (Stream<String> lines = Files.lines(path)) {
        lines.forEachOrdered(System.out::println);
    }
}

使用 Files.lines 方法读取 thermopylae.txt 文件的内容并将其打印到控制台。

使用 Scanner 读取文本文件

Scanner 是一个简单的文本扫描器,可以使用正则表达式解析基本类型和字符串。

Main.java
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

void main() throws FileNotFoundException {

    var fileName = "src/main/resources/thermopylae.txt";

    try (var scanner = new Scanner(new File(fileName))) {

        while (scanner.hasNext()) {

            String line = scanner.nextLine();
            System.out.println(line);
        }
    }
}

该示例使用 Scanner 读取文本文件。

while (scanner.hasNext()) {

    String line = scanner.nextLine();
    System.out.println(line);
}

使用 nextLine 方法逐行读取文件。

使用 InputStreamReader 读取文本文件

InputStreamReader 是从字节流到字符流的桥梁。它读取字节并使用指定的字符集将它们解码为字符。

Main.java
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";

    try (var br = new BufferedReader(new InputStreamReader(
            new FileInputStream(fileName), StandardCharsets.UTF_8))) {

        String line;

        while ((line = br.readLine()) != null) {

            System.out.println(line);
        }
    }
}

该示例使用 InputStreamReader 读取文本文件。

try (var br = new BufferedReader(new InputStreamReader(
        new FileInputStream(fileName), StandardCharsets.UTF_8))) {

InputStreamReaderFileInputStream 创建,后者通过打开与实际文件的连接来创建输入流。然后将 InputStreamReader 传递给 BufferedReader 以提高效率。

Java 7 引入了一个更方便的 API 来使用 InputStreamReader。可以使用 Files.newBufferedReader 创建一个新的缓冲 InputStreamReader

Main.java
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";
    var filePath = Paths.get(fileName);

    try (BufferedReader br = Files.newBufferedReader(
        filePath, StandardCharsets.UTF_8)) {

        String line;

        while ((line = br.readLine()) != null) {

            System.out.println(line);
        }
    }
}

该示例使用 Files.newBufferedReader 方法读取 thermopylae.txt 文件。

使用 Files.readAllBytes 读取文本文件

Files.readAllBytes 方法读取文件中的所有字节。它确保在读取所有字节时关闭文件。

Main.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";
    var filePath = Paths.get(fileName);

    byte[] data = Files.readAllBytes(filePath);
    var content = new String(data);

    System.out.println(content);
}

该示例读取文件中的所有字节,并将它们传递给 String 构造函数。

使用 Files.readString 读取文本

Java 11 引入了一种方便的方法,允许一次性将整个文件读取到字符串中。

Files.readString 将文件中的所有内容读取到字符串中,使用指定的或默认的 (StandardCharsets.UTF_8) 字符集从字节解码为字符。它确保在读取所有内容后关闭文件。

Main.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";
    var filePath = Paths.get(fileName);

    var content = Files.readString(filePath);

    System.out.println(content);
}

该示例将 thermopylae.txt 文件的内容读取到字符串中,并将其打印到终端。

使用 FileChannel 读取文本文件

FileChannel 是用于读取、写入、映射和操作文件的通道。文件通道的优点包括在文件的特定位置读取和写入,加载文件的某个部分或锁定文件的某个部分。

Main.java
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

void main() throws IOException {

    var fileName = "src/main/resources/thermopylae.txt";

    try (RandomAccessFile myFile = new RandomAccessFile(fileName, "rw");
            FileChannel inChannel = myFile.getChannel()) {

        ByteBuffer buf = ByteBuffer.allocate(48);

        int bytesRead = inChannel.read(buf);

        while (bytesRead != -1) {

            buf.flip();

            while (buf.hasRemaining()) {

                System.out.print((char) buf.get());
            }

            buf.clear();
            bytesRead = inChannel.read(buf);
        }
    }
}

该示例使用 FileChannel 读取文本文件。

try (RandomAccessFile myFile = new RandomAccessFile(fileName, "rw");
        FileChannel inChannel = myFile.getChannel()) {

RandomAccessFile 创建 FileChannle

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf);

我们分配一个缓冲区并读取初始数据。

while (bytesRead != -1) {

    buf.flip();

    while (buf.hasRemaining()) {

        System.out.print((char) buf.get());
    }

    buf.clear();
    bytesRead = inChannel.read(buf);
}

我们将数据读取到缓冲区中,并将其写入终端。我们使用 flip 将缓冲区从读取更改为写入。

来源

Java 基本 I/O

在本文中,我们以各种方式在 Java 中读取了文本文件。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写超过 1,400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有Java教程