Java 8+Apache Commons-csv:Jar包中CSV加载失败问题求助
解决Jar包中加载CSV文件时的FileNotFoundException问题
这问题我之前帮同事排查过好几次,核心原因几乎都是开发环境和Jar包环境下的资源访问逻辑不一致导致的——你在Eclipse里测试没问题,是因为此时CSV文件是磁盘上的独立文件,但打包成Jar后,它变成了Jar包内部的一个条目,不能再用常规的File类去访问了。下面给你拆解具体原因和解决办法:
1. 别再用File类访问Jar内的资源
开发时你可能写过类似这样的代码:
File csvFile = new File("src/main/resources/data.csv"); CSVParser parser = CSVParser.parse(csvFile, CSVFormat.DEFAULT);
在Eclipse里,这个路径是相对项目根目录的,能找到文件,但打包成Jar后,src/main/resources下的文件会被放到Jar的根目录,而且Jar内的文件不是磁盘上的实体文件,File类根本无法定位到它。
正确做法:用类加载器的getResourceAsStream()方法读取资源流,这是访问Jar内资源的标准方式:
// 注意路径前的斜杠表示Jar的根目录,如果CSV在某个包下,要写全路径比如/com/yourpackage/data.csv try (InputStream is = CsvLoader.class.getResourceAsStream("/data.csv"); CSVParser parser = CSVParser.parse(is, CSVFormat.DEFAULT.withHeader())) { // 解析逻辑... }
如果是在静态方法中加载,直接用你的类名.class.getResourceAsStream(),避免类加载器上下文问题。
2. 确认CSV文件被正确打包进Jar
有时候问题出在构建环节——你的CSV文件没被复制到Jar里。检查Eclipse的配置:
- 右键项目 → Properties → Java Build Path → Source标签,确保存放CSV的文件夹(比如
src/main/resources)被标记为Source Folder,这样编译时Eclipse会自动把里面的文件复制到输出目录,最终打包进Jar。 - 打包完成后,用压缩软件打开Jar包,直接查看里面有没有你的CSV文件,以及它的路径是否和代码里写的一致。
3. 注意路径大小写问题
Windows系统不区分文件名大小写,但Jar内的资源路径是严格区分大小写的。比如你代码里写的是Data.csv,但实际文件是data.csv,在Eclipse(Windows环境)里能正常读取,但到其他系统或者Jar环境下就会找不到文件。一定要保证代码里的路径和实际文件名完全匹配。
4. 验证示例代码
给你一个完整的可参考的加载类示例,用这种方式写几乎不会出问题:
import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class CsvDataLoader { // 假设你的业务对象是User public static class User { private String id; private String name; // getter和setter省略 public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } } public List<User> loadUsersFromCsv() throws IOException { List<User> userList = new ArrayList<>(); // 从Jar的根目录加载users.csv文件 try (InputStream inputStream = CsvDataLoader.class.getResourceAsStream("/users.csv"); CSVParser csvParser = CSVParser.parse(inputStream, CSVFormat.DEFAULT.withHeader("id", "name").withSkipHeaderRecord())) { for (CSVRecord record : csvParser) { User user = new User(); user.setId(record.get("id")); user.setName(record.get("name")); userList.add(user); } } return userList; } }
按照上面的步骤排查和修改,应该就能解决FileNotFoundException的问题了。
内容的提问来源于stack exchange,提问作者Kyle Grage
相关产品推荐
相关产品推荐

