411. Java 文件操作基础 - 从网络到本地:读取文本资源的两种方式与最佳实践

19 阅读2分钟

411. Java 文件操作基础 - 从网络到本地:读取文本资源的两种方式与最佳实践

🎯 目标

  • 如何通过 HttpClient API 从互联网读取文本资源
  • 如何使用 Files API 从本地文件读取
  • 如何正确处理 异常资源关闭
  • 如何将 InputStream 转换为 Reader 以便逐行读取文本

1️⃣ 在线读取(使用 HttpClient

在有网络连接时,可以直接访问 Gutenberg Project 提供的在线资源。

示例代码:在线读取十四行诗

  • JAVA8
import java.io.*;
import java.net.*;

public class Demo {
    public static void main(String[] args) {
        String urlStr = "https://www.gutenberg.org/cache/epub/1041/pg1041.txt";

        try {
            URL url = new URL(urlStr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(10000);

            int responseCode = connection.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                System.err.println("HTTP request failed with code: " + responseCode);
                return;
            }

            // 读取响应内容,打印前14行
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
                String line;
                int count = 0;
                while ((line = reader.readLine()) != null && count < 14) {
                    System.out.println(line);
                    count++;
                }
            }

            connection.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • JAVA11
import java.io.*;
import java.net.URI;
import java.net.http.*;

public class ReadSonnetsOnline {
    public static void main(String[] args) {
        URI sonnetsURI = URI.create("https://www.gutenberg.org/cache/epub/1041/pg1041.txt");

        HttpRequest request = HttpRequest.newBuilder(sonnetsURI)
                                         .GET()
                                         .build();

        HttpClient client = HttpClient.newHttpClient();

        try {
            HttpResponse<InputStream> response =
                    client.send(request, HttpResponse.BodyHandlers.ofInputStream());

            // 将 InputStream 转换为 Reader,便于逐行读取
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body()))) {
                String line;
                int count = 0;
                while ((line = reader.readLine()) != null && count < 14) {
                    System.out.println(line);
                    count++;
                }
            }

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

要点讲解

  • HttpClient 是 Java 11 引入的现代 HTTP 客户端,替代老旧的 HttpURLConnection
  • HttpResponse.BodyHandlers.ofInputStream() 获取原始字节流,然后用 InputStreamReader 转成字符流。
  • 使用 try-with-resources 确保流在使用后关闭。
  • 示例中只输出前 14 行,避免刷屏。

2️⃣ 本地读取(使用 Files API)

如果提前下载 pg1041.txt 文件,可以直接用 NIO 的 Files 工具类 来读取。

示例代码:本地读取十四行诗

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.*;

public class ReadSonnetsLocal {
    public static void main(String[] args) {
        Path path = Path.of("files/sonnets.txt");

        try (BufferedReader reader = Files.newBufferedReader(path)) {
            String line;
            int count = 0;
            while ((line = reader.readLine()) != null && count < 14) {
                System.out.println(line);
                count++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

要点讲解

  • Files.newBufferedReader(path) 直接返回一个 BufferedReader,方便逐行读取文本。
  • 仍然使用 try-with-resources 来自动关闭资源。
  • 整体写法比 HttpClient 更简单,因为本地文件访问比网络请求更可靠。

3️⃣ 两种方式对比

方式使用场景优点缺点
HttpClient在线读取不需手动下载,随时获取最新内容依赖网络,速度受限
Files API本地读取高效、稳定,无需网络需要事先下载文件

4️⃣ 扩展思考

  • 如果文件非常大,是否应该一次性读取? 👉 答案:不要。应使用 逐行流式读取,避免内存溢出。

  • 如果要处理文本编码(如 UTF-8 / ISO-8859-1)怎么办? 👉 可以在 InputStreamReaderFiles.newBufferedReader 里指定编码:

    new InputStreamReader(response.body(), StandardCharsets.UTF_8);
    Files.newBufferedReader(path, StandardCharsets.UTF_8);