- 自从梳理清楚了与Java文件有关的输入/输出流,现在读取或写入文件基本都不需要上网查资料了,简直磨刀不误砍柴工~
- 感兴趣的,可以查看本人之前的博客:基于文件的java输入/输出流
-
现在有个需求:读取countries文件,计算世界上有多少个国家
-
创建maven项目,编写代码、本地运行,那是溜溜的,几下就完成了
// 其他import省略,只展示sl4j的 import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CountriesTest { private static final Logger logger = LoggerFactory.getLogger(CountriesTest.class); public static void main(String[] args) { try { CountriesTest test = new CountriesTest(); test.countCountries1(); } catch (IOException e) { logger.error("读取文件失败", e); } } public void countCountries1() throws IOException { // 获取文件目录 String filePath = this.getClass().getResource("/").getPath().replace("/target/classes/", ""); logger.info("开始从指定目录读取文件, {} ...", filePath); try (BufferedReader reader = new BufferedReader(new FileReader(filePath + "/countries"))) { int count = 0; String country = reader.readLine(); while (country != null) { count++; // 获取下一个国家 country = reader.readLine(); } logger.info("There are {} countries in the world", count); } } } -
其中,slf4j的maven依赖为
org.slf4j slf4j-api 1.7.30 ch.qos.logback logback-classic 1.2.3 -
countries文件,放在maven模块的父目录下:
-
countries文件的内容,是从网页上粘贴的,部分内容如下:
Afghanistan Albania Algeria Andorra
-
现在需求升级:将代码打包成jar包,放到服务器上执行
-
这也很简单,一个打包命令mvn clean package就搞定
-
结果到服务器上执行时,却报错了。
-
通过对比代码,发现如下代码存在空指针问题
String filePath = this.getClass().getResource("/").getPath().replace("/target/classes/", ""); -
自己解压缩对应jar包,也没有在jar包里面找到countries文件。所以,即使文件目录正确,文件不存在,也会读取失败
-
灵机一动,想到Java项目中还有个src/main/resources目录,
-
Java Web项目中很多配置文件都是放在这里面的,打包时,好像也没有做什么额外的配置,最后还能读取这些文件
-
抱着试一试的心理,将countries文件移动到了resources目录
-
然后参考博客:java项目中获得resources目录下的文件或图片,直接以文件流的形式读取resources目录下的countries文件
-
最终完整的代码如下:
public class CountriesTest { private static final Logger logger = LoggerFactory.getLogger(CountriesTest.class); public static void main(String[] args) { try { CountriesTest test = new CountriesTest(); test.countCountries2(); } catch (IOException e) { logger.error("读取文件失败", e); } } public void countCountries2() throws IOException { logger.info("开始从resources目录读取文件 ..."); // 获取resources下的文件资源 InputStream in = getClass().getResourceAsStream("/countries"); try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { int count = 0; String country = reader.readLine(); while (country != null) { count++; // 获取下一个国家 country = reader.readLine(); } logger.info("There are {} countries in the world", count); } catch (IOException e) { throw e; } } } -
重新打包后,成功读取文件
-
同事,jar的根目录下出现了countries文件 —— 说明countries文件被成功打包
-
将文件放在resources目录可以自动打包,如果放到其他层级呢?
-
下面是笔者的一些试验:
目录 是否ok 是否打包 src/main/java 目录 failed No src/main/resources/files目录 ok,需要将文件路径更新为InputStream in = getClass().getResourceAsStream("/files/countries"); Yes,在files/目录下 src/files目录 failed No
-
通过网上查阅资料,发现maven resources plugin,可以指定resources目录
-
按照官网描述,默认的resources目录为src/main/resources,可以通过如下方式在
标签中指定resources目录 resource1 resource2 resource3 -
以将countries文件放到src/main/java 目录为例,配置如下:
src/main/java src/main/resources
-
在resources目录下,有各种类型的文件,只有某些文件在文件运行时是需要的
-
这时,可以通过
或 指定或排除文件,详情参考官网:Including and excluding files and directories src/main/java ***.bmp ...
-
文件中,某些变量需要在编译时更新。如hello.txt中,包含${name}
Hello ${name} -
可以通过开启filtering属性,将${name}更新为实际值
src/main/resources true
- 而${name}的来源主要有三种,具体参考官网:Filtering
- maven自带的属性,如${basedir}、${name},可以参考作者之前的博客:10. maven属性,或者网上查阅资料
- 执行maven命令是,通过-Dxxx传入的值,类似mvn resources:resources -Dname="world"
- 自定义的property,可以放在pom文件中,也可以使用单独的.properties文件存储



