# 在 Java 中读取文本文件

原文：http://zetcode.com/java/readtext/

在 Java 中阅读文本文件教程中，我们展示了如何在 Java 中阅读文本文件。 我们使用内置工具，包括`FileReader`，`InputStreamReader`和`Scanner`。 另外，我们使用 API​​ Google Guava 库。

Google Guava 是 Java 的通用库集； 该集合也包括 IO API。

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

`src/resources/thermopylae.txt`

```java
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/resources/`目录中。

## Java `FileReader`类

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

*   java.io.FileReader
*   java.nio.file.Files
*   java.util.Scanner
*   java.io.InputStreamReader
*   com.google.common.io.Files

## Java 使用`FileReader`读取文本文件

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

> **注意**：过去，`FileReader`依赖于默认平台的编码。 从 Java 11 开始，此问题已得到纠正。 现在可以显式指定编码。

`com/zetcode/FileReaderEx.java`

```java
package com.zetcode;

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

public class FileReaderEx {

    public static void main(String[] args) throws IOException {

        var fileName = "src/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`文件读取文本。

```java
var fileName = "src/resources/thermopylae.txt";

```

在`fileName`变量中，我们存储文件的路径。

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

```

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

```java
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()`返回系统相关的行分隔符字符串。

## Java 使用`Files.readAllLines`读取文本文件

`Files.readAllLines()`方法从文件读取所有行。 此方法可确保在读取所有字节或引发异常后关闭文件。 使用指定的字符集将文件中的字节解码为字符。

请注意，此方法将整个文件读入内存。 因此，它可能不适用于非常大的文件。

`com/zetcode/ReadAllLinesEx.java`

```java
package com.zetcode;

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

public class ReadAllLinesEx {

    public static void main(String[] args) throws IOException {

        var fileName = "src/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`文件的内容并将其打印到控制台。

## 使用 Java8 流 API 读取文本文件

读取文本文件的另一种方法是使用 Java8 流 API。 `Files.lines()`从文件中读取所有行作为流。 使用`StandardCharsets.UTF-8`字符集将文件中的字节解码为字符。

`com/zetcode/FilesLinesEx.java`

```java
package com.zetcode;

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

public class FilesLinesEx {

    public static void main(String[] args) throws IOException {

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

        Files.lines(Paths.get(fileName)).forEachOrdered(System.out::println);
    }
}

```

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

## Java 使用`Scanner`读取文本文件

`Scanner`是简单的文本扫描器，可以使用正则表达式解析原始类型和字符串。

`com/zetcode/ScannerEx.java`

```java
package com.zetcode;

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

public class ScannerEx {

    public static void main(String[] args) throws FileNotFoundException {

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

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

            while (scanner.hasNext()) {

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

```

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

```java
while (scanner.hasNext()) {

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

```

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

## Java 使用`InputStreamReader`读取文本文件

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

`com/zetcode/InputStreamReaderEx.java`

```java
package com.zetcode;

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

public class InputStreamReaderEx {

    public static void main(String[] args) throws IOException {

        var fileName = "src/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`读取文本文件。

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

```

`InputStreamReader`是从`FileInputStream`创建的，它通过打开与实际文件的连接来创建输入流。 然后将`InputStreamReader`传递给`BufferedReader`，以提高效率。

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

`com/zetcode/InputStreamReaderEx2.java`

```java
package com.zetcode;

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

public class InputStreamReaderEx2 {

    public static void main(String[] args) throws IOException {

        var fileName = "src/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`文件。

## Java 使用`Files.readAllBytes`读取文本文件

`Files.readAllBytes()`方法从文件读取所有字节。 它确保在读取所有字节后关闭文件。

`com/zetcode/ReadAllBytesEx.java`

```java
package com.zetcode;

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

public class ReadAllBytesEx {

    public static void main(String[] args) throws IOException {

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

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

        System.out.println(content);
    }
}

```

该示例从文件读取所有字节，并将它们传递给`String`构造器。

## Java 使用`Files.readString`读取文本

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

`Files.readString`将文件中的所有内容读取为字符串，并使用指定的或默认的（`StandardCharsets.UTF_8`）字符集将字节解码为字符。 它确保在读取所有内容后关闭文件。

`com/zetcode/ReadFileAsStringEx.java`

```java
package com.zetcode;

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

public class ReadFileAsStringEx {

    public static void main(String[] args) throws IOException {

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

        var content = Files.readString(filePath);

        System.out.println(content);
    }
}

```

该示例将`thermopylae.txt`文件的内容读取为字符串，然后将其打印到终端。

## Java 使用`FileChannel`读取文本文件

`FileChannel`是用于读取，写入，映射和操作文件的通道。 文件通道的优点包括在文件的特定位置进行读写，加载文件的一部分或锁定文件的一部分。

`com/zetcode/FileChannelEx.java`

```java
package com.zetcode;

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

public class FileChannelEx {

    public static void main(String[] args) throws IOException {

        var fileName = "src/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`读取文本文件。

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

```

从`RandomAccessFile`创建一个`FileChannle`。

```java
ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf);

```

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

```java
while (bytesRead != -1) {

    buf.flip();

    while (buf.hasRemaining()) {

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

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

```

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

## 使用 Google Guava 读取文本文件

Google Guava 是一个 Java 帮助程序库，也具有 IO 工具。 如果要读取的文件很大，则以下两个 Guava 方法将消耗大量系统资源。

`pom.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
            http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>readtextguavaex</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>12</maven.compiler.source>
        <maven.compiler.target>12</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>
    </dependencies>

</project>

```

这是 Maven POM 文件。

`com/zetcode/ReadTextGuavaEx.java`

```java
package com.zetcode;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class ReadTextGuavaEx {

    public static void main(String[] args) throws IOException {

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

        List<String> lines = Files.readLines(new File(fileName),
                Charsets.UTF_8);

        var sb = new StringBuilder();

        for (String line: lines) {

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

        System.out.println(sb);
    }
}

```

在示例中，我们使用`Files.readLines()`方法从文件中读取所有行。 该方法返回字符串列表。 将默认字符集指定为第二个参数。

在第二个示例中，我们使用`Files.asCharSource()`。

`com/zetcode/ReadTextGuavaEx2.java`

```java
package com.zetcode;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;

public class ReadTextGuavaEx2 {

    public static void main(String[] args) throws IOException {

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

        var charSource = Files.asCharSource(new File(fileName), 
            Charsets.UTF_8).read();

        System.out.println(charSource);
    }
}

```

`Files.asCharSource()`用于使用给定的字符集从给定的文件读取字符数据。 它的`read()`方法以字符串形式读取此源的内容。

在本文中，我们已经用 Java 的各种方式读取了文本文件。

您可能也对以下相关教程感兴趣： [Java 列表目录内容](/articles/javalistdirectory/)， [Java `FileOutputStream`教程](/java/fileoutputstream/)，[用 Java 复制文件](/java/copyfile/)， [Java 教程](/lang/java/)，[使用 Java8 的`StringJoiner`连接字符串](/articles/java8stringjoiner/) ，[Java 网页读取](/articles/javareadwebpage/)或 [Google Guava 简介](/articles/guava/)。

列出[所有 Java 教程](/all/#java)。