Java 读取文件

在 Java 中有多种读取文件内容的方式。

  1. Files.readAllLines 读取文件到 List(Java 8)
  2. Files.readAllBytes 读取文件到 byte\[] 数组(Java 8)
  3. Files.lines 读取文件内容到 Stream 流 (Java 8 )
  4. Files.readString 读取文件到字符串(Java 11)
  5. , 按行读取文件( Java 1.1 +)
  6. BufferedInputStream 按字节读取文件(Java 1.0 +)
  7. Scanner 读取文件(Java 1.5+,很少用)

文件读取操作需要注意关闭输入流,自 Java 7 开始,可以通过 try-with-resource 方式自动关闭流。详情可以参考:Try-with-resource

读取文件还需要注意文件大小,如果文件过大,一次性读取到内存中,可能会发生内存溢出

本文读取示例文件:

➜ pwd
/Users/darcy/wdbyte
➜ cat log.txt
111 hello
222 www
333 wdbyte
444 com

Files.readAllLines ⭐️

Java 7 新增了 Files 类,Java 8 增加了 readAllLines 方法,可以直接读取文件内容到 List<String

Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
for (String line : lines) {
    System.out.println(line);
}

运行结果:

111 hello
222 www
333 wdbyte
444 com

Files.readAllBytes ⭐️

使用 Files.readAllBytes 可以读取文件内容到字节数组。

Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
byte[] bytes = Files.readAllBytes(path);
String content = new String(bytes, StandardCharsets.UTF_8);
System.out.println(content);

Files.lines ⭐️

Java 新增了 Files.line 可以读取文件为 Stream 流,然后可以按行读取。注意 stream 流需要关闭,下面的示例中通过 try 方式自动关闭。

Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
try (Stream<String> stream = Files.lines(path);) {
    stream.forEach(System.out::println);
}

对于大文件,也可以使用 parallel 并行流读取,遍历时可以使用 forEachOrdered 保证顺序。

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

Files.readString

Java 11 开始,增加了 Files.readString 可以直接读取文件内容为一个字符串。但是要求文件内容大小不能超过 2G。

Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
String content = Files.readString(path, StandardCharsets.UTF_8);
System.out.println(content);

运行输出:

111 hello
222 www
333 wdbyte
444 com

BufferedReader

BufferedReader 是自 Java 1.1 就存在的文件读取方式,很多新方法也是它的再次封装。

File file = new File("/Users/darcy/wdbyte/log.txt");
String line;
// 默认读取缓冲区大小 8K
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
} catch (IOException e) {
    throw new RuntimeException(e);
}

运行输出:

111 hello
222 www
333 wdbyte
444 com

BufferedReader 可以设置缓冲区大小,提高缓冲区大小,可以在读取大文件时提高速度。

// 定义缓冲区大小为 128 K
int buffer = 128 * 1024;
try (BufferedReader br = new BufferedReader(new FileReader(file), buffer)) {
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
} catch (IOException e) {
    throw new RuntimeException(e);
}

从 Java 8 开始,可以直接通过 Files 类构造 BufferedReader

Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
String line;
try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8);) {
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}

BufferedInputStream

自 Java 1.0 就存在的读取方式,可以按字节读取文件内容。

File file = new File("/Users/darcy/wdbyte/log.txt");
try (FileInputStream fis = new FileInputStream(file);
     BufferedInputStream bis = new BufferedInputStream(fis);) {

    StringBuilder content = new StringBuilder();
    int data;
    while ((data = bis.read()) != -1) {
        content.append((char)data);
    }
    System.out.println(content.toString());
} catch (IOException e) {
    e.printStackTrace();
}

Scanner

Scanner 读取文件,很少使用。

File file = new File("/Users/darcy/wdbyte/log.txt");
try (Scanner sc = new Scanner(new FileReader(file))) {
    while (sc.hasNextLine()) {
        String line = sc.nextLine();
        System.out.println(line);
    }
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
}

Apache Commons IO

引入依赖:

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

读取文件所有内容。

public void readFileByApacheCommons() throws IOException {
    File file = new File("/Users/darcy/wdbyte/test.txt");
    List<String> list = FileUtils.readLines(file, StandardCharsets.UTF_8);
    for (String data : list) {
        System.out.println(data);
    }
}

一如既往,文章中代码存放在 Github.com/niumoo/javaNotes.