Java 实例 – 读取文件内容(千字长文)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 Java 编程中,读取文件内容是一个基础但至关重要的技能。无论是处理配置信息、日志分析,还是构建数据驱动的应用程序,开发者都需要与文件系统进行交互。对于编程初学者而言,理解如何高效、安全地读取文件内容,是迈向成熟开发能力的重要一步。对于中级开发者来说,掌握不同场景下的文件读取方法,能够帮助优化代码性能并提升代码的可维护性。本文将通过 Java 实例 – 读取文件内容 这一主题,从基础到进阶,系统性地讲解 Java 中读取文件的多种方法,并通过实际案例演示其应用场景。


一、Java 文件读取的核心概念与准备

1.1 文件路径的表示

在 Java 中,文件路径可以分为 绝对路径相对路径

  • 绝对路径:指向文件系统中某个文件的具体位置,例如 C:\data\example.txt(Windows)或 /home/user/file.txt(Linux/macOS)。
  • 相对路径:相对于当前程序的工作目录(通常是项目根目录或运行时目录)。例如,如果文件与 Java 类文件在同一目录下,可直接使用 file.txt

比喻:可以将绝对路径想象成快递员上门送货时需要的完整地址,而相对路径则是“隔壁房间的抽屉里”,依赖于当前位置的相对位置。

1.2 文件读取的基本流程

读取文件的通用步骤如下:

  1. 打开文件流:通过 FileInputStreamFileReader 等类建立与文件的连接。
  2. 读取数据:逐字节或逐字符地读取文件内容。
  3. 关闭流:释放系统资源,避免内存泄漏。

注意:在 Java 7 及以后版本中,可以通过 try-with-resources 语句自动关闭流,减少资源泄漏的风险。


二、传统 IO 方法:使用 FileReaderBufferedReader

2.1 基础代码示例

以下是一个经典的文件读取实例:

import java.io.*;  

public class FileReaderExample {  
    public static void main(String[] args) {  
        String filePath = "data.txt";  
        try (FileReader fileReader = new FileReader(filePath);  
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {  
            String line;  
            while ((line = bufferedReader.readLine()) != null) {  
                System.out.println(line);  
            }  
        } catch (IOException e) {  
            System.out.println("Error reading file: " + e.getMessage());  
        }  
    }  
}  

2.2 关键知识点解析

  • FileReader:用于读取字符文件,但它直接读取字节流并转换为字符,可能导致编码问题(例如中文乱码)。
  • BufferedReader:通过缓冲机制提升读取效率,避免频繁调用底层系统接口。
  • readLine():逐行读取文件内容,适合处理文本文件。

比喻FileReader 是“原始快递员”,直接搬运文件中的字节;而 BufferedReader 则像“快递分拣中心”,通过批量处理提高效率。


三、Java NIO:使用 FilesPath 实现现代化读取

Java 7 引入的新 IO(NIO.2)提供了更简洁的 API,例如 Files 工具类和 Path 接口。

3.1 单行读取与多行读取

3.1.1 单行读取(适用于小型文件)

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

public class NioExample {  
    public static void main(String[] args) {  
        Path path = Paths.get("data.txt");  
        try {  
            String content = Files.readString(path);  
            System.out.println(content);  
        } catch (IOException e) {  
            System.err.println("Error: " + e.getMessage());  
        }  
    }  
}  
  • Files.readString():一次性读取整个文件内容为字符串,适合文件较小的场景。

3.1.2 分行读取(适用于大型文本文件)

import java.nio.file.*;  
import java.util.List;  

public class ReadLinesExample {  
    public static void main(String[] args) {  
        Path path = Paths.get("large_file.txt");  
        try {  
            List<String> lines = Files.readAllLines(path);  
            for (String line : lines) {  
                System.out.println(line);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  
  • Files.readAllLines():将文件内容按行分割为 List<String>,适合需要遍历行数据的场景。

3.2 NIO 的优势

  • 简洁性:通过静态方法直接操作文件,减少代码冗余。
  • 编码支持:默认使用 UTF-8 编码,避免了传统 IO 的乱码问题。
  • 路径标准化Path 接口提供跨平台的路径处理能力。

四、进阶技巧与常见问题处理

4.1 处理编码问题

如果文件使用非 UTF-8 编码(如 GBK),需通过 Charset 显式指定:

import java.nio.file.*;  
import java.nio.charset.StandardCharsets;  

public class EncodingExample {  
    public static void main(String[] args) {  
        Path path = Paths.get("chinese.txt");  
        try {  
            String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);  
            System.out.println(content);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  

4.2 异常处理与资源管理

在传统 IO 中,需手动关闭流:

FileReader fileReader = null;  
BufferedReader bufferedReader = null;  
try {  
    fileReader = new FileReader("data.txt");  
    bufferedReader = new BufferedReader(fileReader);  
    // ...  
} finally {  
    if (bufferedReader != null) {  
        bufferedReader.close();  
    }  
    if (fileReader != null) {  
        fileReader.close();  
    }  
}  

而通过 try-with-resources(Java 7+)可以自动关闭资源:

try (FileReader fileReader = new FileReader("data.txt");  
     BufferedReader bufferedReader = new BufferedReader(fileReader)) {  
    // ...  
} catch (IOException e) {  
    // ...  
}  

4.3 性能对比与选择建议

方法特点适用场景
传统 IO(FileReader + BufferedReader灵活、兼容旧版本需要逐行处理或兼容 Java 6 及以下版本
NIO(Files.readString()简洁、跨平台小型文件或需要快速获取完整内容
NIO(Files.readAllLines()自动按行分割需要遍历行数据且文件不超内存

五、实战案例:读取 CSV 文件并解析

5.1 需求描述

假设有一个 users.csv 文件,内容如下:

id,name,age  
1,Alice,30  
2,Bob,25  

目标是读取该文件并提取用户信息。

5.2 实现代码

import java.io.*;  
import java.util.ArrayList;  
import java.util.List;  

public class CsvReader {  
    public static void main(String[] args) {  
        String filePath = "users.csv";  
        List<User> users = new ArrayList<>();  
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {  
            // 跳过表头  
            br.readLine();  
            String line;  
            while ((line = br.readLine()) != null) {  
                String[] fields = line.split(",");  
                User user = new User(  
                    Integer.parseInt(fields[0]),  
                    fields[1],  
                    Integer.parseInt(fields[2])  
                );  
                users.add(user);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        // 打印结果  
        users.forEach(System.out::println);  
    }  

    static class User {  
        int id;  
        String name;  
        int age;  

        User(int id, String name, int age) {  
            this.id = id;  
            this.name = name;  
            this.age = age;  
        }  

        @Override  
        public String toString() {  
            return "User[id=" + id + ", name=" + name + ", age=" + age + "]";  
        }  
    }  
}  

5.3 运行结果

User[id=1, name=Alice, age=30]  
User[id=2, name=Bob, age=25]  

六、结论

本文通过 Java 实例 – 读取文件内容 的讲解,系统性地介绍了传统 IO、NIO 以及现代 Java 特性(如 try-with-resources)的实现方式。无论是编程初学者还是中级开发者,都能从中找到适合自身场景的解决方案。

对于初学者,建议从 BufferedReader 入手,逐步掌握基础流操作;对于中级开发者,可探索 NIO 的高级功能(如异步读取或通道操作)。在实际开发中,需根据文件大小、编码格式和性能需求,选择最合适的实现方式。

掌握文件读取技术不仅是 Java 编程的基础,更是构建复杂应用(如日志分析、数据处理工具)的重要基石。通过持续实践与优化,开发者能够进一步提升代码的健壮性和效率。


本文通过结构化讲解、代码示例和性能对比,全面覆盖了 Java 文件读取的核心知识点,帮助读者在不同场景下灵活应用技术方案。

最新发布