资源文件路径问题

概述

  • 我们在写Java程序的时候经常会遇到读写文件的情况。要想读取一个文件首先要获取到它的文件路径。
  • 一个文件的文件路径有很多种获取方式,对于不同的情况有不同的获取方式。
  • 比如我们要获取一个文件的字节输入流,打印这个文件的内容,我们有多种方式获取它的路径。

绝对路径方式

  • 最简单粗暴的就是使用绝对路径的方式了,如下通过绝对路径获取一个文件字节输入流
FileInputStream f = new FileInputStream("D:\\workspace\\idea-project\\a.txt");
System.out.println(f);
  • 但是绝对路径太不灵活了,如果项目的位置改变了,那么这些文件路径都要改变。

相对路径方式

  • 相对路径的概念我们都清楚,但是如果我们要在Test.java这个类中利用相对路径获取文件输入流,那么到底相对于谁定位呢?
  • 以前写前端的时候,如果是html页面之间的跳转,它是相对当前html文件的位置进行定位的。
  • 而对于Java代码,idea会将整个src目录的java文件编译为class文件存放在out目录下一个目录中,如果我们在Test.java同级目录创建一个a.txt文件。在编译完成后,会在生成的Test.class文件同级目录生成一个a.txt文件。
  • 我们在Test.java同级目录下创建一个a.txt文件,然后获取这个文件看是否会成功
FileInputStream f = new FileInputStream("a.txt");
System.out.println(f);
  • 最终抛出了找不到指定文件的异常,说明此时的相对路径并不是基于当前Java文件或class文件来定位的。
  • 其实idea的相对定位是相对于当前项目的根目录(不是module根目录)进行定位的,我们将a.txt文件移动到整个project的根目录下面然后再执行以下代码
FileInputStream f = new FileInputStream("a.txt");
System.out.println(f);
  • 此时便可以成功访问到a.txt这个文件了。
  • 基于项目根目录我们就可以访问整个项目下任何一个文件了
    FileInputStream f = new FileInputStream(“模块名\包名\文件名”);
    System.out.println(f);

基于classpath的方式

  • 不管是绝对定位还是相对定位的方式都是在本地文件系统读取文件的方式,但是如果我要在web项目中读取文件呢?

  • 如果用maven构建一个web工程,我们知道所有的java文件最终会被编译为classes文件存放到target目录下的classes目录,但是java目录下的其他文件会被丢弃,不会存放在classes目录中。

  • 为了解决这个问题,maven提供了一个resource资源目录,我们可以把所有的资源文件放在这个目录,等项目编译打包完毕,所有的资源文件会存放到classes目录下。

  • 如果我们在maven工程中读取一个json文件,我们可以这样实现,首先将json文件存放到resources目录中,然后在java代码中从项目根目录开始相对定位到classes目录下的指定json文件。代码如下:
    FileReader re = new FileReader(“module名\target\classes\mylink-data.json”);

  • 可以发现调用对应方法执行代码之后可以正常读取到json文件。

  • 但是我们把整个web项目启动起来通过servlet调用读取json文件的方法,就会抛出找不到指定文件的错误。因为把整个web项目是在tomcat服务器上运行的,而相对路径是基于本地项目根目录的方式来定位的肯定会失败。此时就要使用新的获取文件路径的方式了。

  • 使用Class.getResource方法获取文件路径

String s1 =  this.getClass().getResource("").getPath(); 
//获取当前类所对应的那个class文件的所在目录
String s2 =  this.getClass().getResource("/").getPath(); 
//如果是本地项目获取out目录下的模块名目录(对应就是module的src目录),如果是maven工程,获取target下的classes目录(对应就是resource目录)
  • 使用ClassLoader.getResource方法获取文件路径
String s1 = this.getClass().getClassLoader().getResource("").getPath(); 
//如果是本地项目获取out目录下的模块名目录(对应就是module的src目录),如果是maven工程,获取target下的classes目录(对应就是resource目录)
String s2 = this.getClass().getClassLoader().getResource("a.txt").getPath();
//如果是本地项目,获取src目录下a.txt文件,如果是maven工程获取resources目录下的a.txt文件
  • 使用Thread.currentThread().getContextClassLoader().getResource("").getPath();获取路径,与ClassLoader.getResource效果一样。

基于ServletContext 的方式

  • 基于classpath的方式主要用于获取后端自己的配置文件等,而基于ServletContext 的方式可以操作前端的静态资源。
  • 它是以静态资源根目录为标准进行定位的(即index.html所在那个目录)
ServletContext context = req.getServletContext();
String realpath = context.getRealPath("/a.txt");
BufferedReader in = new BufferedReader(new FileReader(realpath));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值