在 Java 中阅读文本文件教程中,我们展示了如何在 Java 中阅读文本文件。 我们使用内置工具,包括FileReader
,InputStreamReader
和Scanner
。 另外,我们使用 API Google Guava 库。
Google Guava 是 Java 的通用库集; 该集合也包括 IO API。
以下示例使用此文本文件。
src/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/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
是用于读取字符文件的类。 它使用默认缓冲区大小从字符文件中读取文本。 从字节到字符的解码使用指定的字符集或平台的默认字符集。
Note: In the past, FileReader
relied on the default platform’s encoding. Since Java 11, the issue was corrected. It is possible now to explicitly specify the encoding.
com/zetcode/FileReaderEx.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
文件读取文本。
var fileName = "src/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()
返回系统相关的行分隔符字符串。
Java 使用Files.readAllLines
读取文本文件
Files.readAllLines()
方法从文件读取所有行。 此方法可确保在读取所有字节或引发异常后关闭文件。 使用指定的字符集将文件中的字节解码为字符。
请注意,此方法将整个文件读入内存。 因此,它可能不适用于非常大的文件。
com/zetcode/ReadAllLinesEx.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
文件的内容并将其打印到控制台。
使用 Java 8 流 API 读取文本文件
读取文本文件的另一种方法是使用 Java 8 流 API。 Files.lines()
从文件中读取所有行作为流。 使用StandardCharsets.UTF-8
字符集将文件中的字节解码为字符。
com/zetcode/FilesLinesEx.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
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
读取文本文件。
while (scanner.hasNext()) {
String line = scanner.nextLine();
System.out.println(line);
}
使用nextLine()
方法逐行读取文件。
Java 使用InputStreamReader
读取文本文件
InputStreamReader
是从字节流到字符流的桥梁。 它读取字节,并使用指定的字符集将其解码为字符。
com/zetcode/InputStreamReaderEx.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
读取文本文件。
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
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
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
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
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
读取文本文件。
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()
将缓冲区从读取更改为写入。
使用 Google Guava 读取文本文件
Google Guava 是一个 Java 帮助程序库,也具有 IO 工具。 如果要读取的文件很大,则以下两个 Guava 方法将消耗大量系统资源。
pom.xml
<?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
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
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 的各种方式读取了文本文件。