⛳ 如何使用 getResourceAsStream() 加载文件

⛳ 如何使用 getResourceAsStream() 加载文件

🏭 一,简介

getResourceAsStream() 是java中用于加载资源文件的方法之一。

它是 ClassLoaderClass 类提供的方法,用于从类路径(ClassPath)中获取资源文件并返回一个输入流 (InputStream。这个方法常用于加载配置文件,模板文件,图片,音频等各种类型的资源。

方法签名:

InputStream getResourceAsStream(String name);

参数:

  • name : 表示要加载的资源文件的路径,可以是相对路径或绝对路径。对于相对路径,其起始点通常是调用 getResourceAsStream() 方法的类或类加载器的位置,需要看是YouClassName.class.getResourceAsStream()调用, 还是 YouCalssName.class.getClassLoader().getResourceAsStream()调用。具体细节看下文。

返回值:

  • 如果找到资源文件,则返回一个 InputStream 对象,允许你以字节流的方式读取资源文件的内容。
  • 如果找不到资源文件,则返回 null 。

注意事项:

  • getResourceAsStream()方法在查找资源文件时,会根据调用它的类或类加载器的位置来查找资源。如果资源文件不在相应的类路径下,可能会导致找不到资源的情况。
  • 路径参数一般以/开头表示从类路径的根目录开始查找资源,不以 / 开头表示从调用它的类所在的包路径开始查找资源。
    • 如何获取根路径和包路径:

      public class GetResourceTest {
          public static void main(String[] args) {
              /**
               * 获取根路径和包路径
               */
              URL resource = GetResourceTest.class.getClassLoader().getResource("a123.txt");
              String path = resource.getPath();
              System.out.println("根路径:" + path);
              URL resource1 = GetResourceTest.class.getResource("");
              String path1 = resource1.getPath();
              System.out.println("包路径" + path1);
          }
      }
      
      // 结果
      //根路径:/D:/Code/pracitice/untitled/target/classes/a123.txt
      //包路径/D:/Code/pracitice/untitled/target/classes/org/example/test/
      

      项目结构:

      image-20230722135948220

      image-20230722140005221

👣 二,示例用法

💻 2.1,不使用类加载器(ClassLoader

// 假设要加载名为"config.properties"的配置文件
InputStream inputStream = YourClassName.class.getResourceAsStream("/config.properties");

// 使用BufferedReader读取配置文件内容
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    // 处理异常
}

注:YourClassName是当前类的类名,用于定位类路径。可以通过这种方式加载任何类型的资源文件,并以输入流的形式读取其内容,无需关心资源文件的具体位置。

📢 2.2,使用类加载器(ClassLoader

/**
     *  zip 压缩文件部署
     * @throws IOException
     */
    @Test
    public void deployProcessByZip() throws IOException {
        // 定义zip输入流
        InputStream inputStream = this.getClass()  // getClass() 返回:表示此对象的运行时类的Class对象。
                .getClassLoader()   // 返回:装入此对象表示的类或接口的类装入器。
                .getResourceAsStream("process/process.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        // 流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .name("请假申请流程")
                .deploy();
        System.out.println("流程部署id: " + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }

🎉 三,使用类加载器(ClassLoader)和不使用类加载器的区别

案例:

this.getClass()  // getClass() 返回:表示此对象的运行时类的Class对象。
    .getClassLoader()   // 返回:装入此对象表示的类或接口的类装入器。
    .getResourceAsStream("process/process.zip");


this.getClass()  // getClass() 返回:表示此对象的运行时类的Class对象
    .getResourceAsStream("process/process.zip");  
  1. this.getClass().getClassLoader().getResourceAsStream("process/process.zip"): 这种方式使用类加载器(ClassLoader)来加载资源文件。类加载器是用于加载类的机制,并且每个类加载器都有自己的类加载路径。getResourceAsStream方法的路径是相对于类加载器的根路径。因此,"process/process.zip" 这个路径将相对于类加载器的根路径来定位资源文件。

    在一些情况下,特别是当使用不同的类加载器(例如自定义类加载器)加载类时,this.getClass().getClassLoader().getResourceAsStream("process/process.zip") 可能更可靠,因为它直接使用类加载器的路径,不受当前类的位置的影响。

  2. this.getClass().getResourceAsStream("process/process.zip"): 这种方式使用当前类的类加载器来加载资源文件。getResourceAsStream方法的路径是相对于当前类所在的包路径(package path)。换句话说,它会在当前类的包路径下寻找资源文件。

    这种方式适用于当前类和资源文件在同一个包路径下的情况。如果资源文件与当前类在不同的包路径下,或者资源文件位于类加载器的根路径(Classpath根目录)下,这种方式可能会失败,因为它是相对于当前类所在的包路径来定位资源文件。

所以,总的来说,两种方式都可以加载资源文件,但要根据你的具体情况来选择哪种方式更合适。如果你需要在不同类加载器的情况下加载资源文件或者资源文件位于类加载器的根路径下,推荐使用this.getClass().getClassLoader().getResourceAsStream("process/process.zip");如果资源文件与当前类在同一个包路径下,那么 this.getClass().getResourceAsStream("process/process.zip") 是更直观的选择。

当我看到这里,还是有一点不明白,在this.getClass().getClassLoader().getResourceAsStream("process/process.zip")调用中,getResourceAsStream方法的路径是相对于类加载器的根路径。那么,这个类加载的根路径是哪里呢?

🚜 四,ClassLoader的根路径是在哪里?

类加载器的根路径,也称为Classpath根路径,是类加载器用于查找类和资源文件的基本路径。在Java中,有三种主要的类加载器:

  1. Bootstrap ClassLoader(启动类加载器):
    • 它是JVM的一部分,用于加载JVM自身的核心类,如java.lang.Objectjava.lang.String等。
    • 它没有确定的文件系统路径,它是用本地代码实现的,并且通常由JVM自动加载。
  2. Extension ClassLoader(扩展类加载器):
    • 它是由sun.misc.Launcher$ExtClassLoader表示的,负责加载Java的扩展库(extensions)。
    • 它的类路径通常是${java.home}/lib/ext/目录,其中${java.home}是JDK的安装目录。
  3. System ClassLoader / Application ClassLoader(系统类加载器/应用程序类加载器):
    • 它是由sun.misc.Launcher$AppClassLoader表示的,负责加载应用程序的类和资源文件。
    • 它的类路径通常是由java.class.path系统属性指定的,包括当前工作目录和所有被指定的JAR文件或目录。

对于系统类加载器,其类路径包含了Classpath根路径。在绝大多数情况下,Classpath根路径是项目构建(如Maven或Gradle项目)的src/main/resources目录。在这个目录下的资源文件,通过getClass().getResourceAsStream()或者getClass().getClassLoader().getResourceAsStream()来访问。

请注意,类加载器可以是层次结构的,当一个类加载器无法加载类或资源时,它会委托给父类加载器来尝试加载。因此,资源的查找顺序是从下往上,即从当前类加载器的类路径开始,然后向上层级查找,直到找到资源或到达Bootstrap ClassLoader。

💖 五,ClassClassLoader 加载资源的区别

📝 5.1,资源访问方式

资源(resource) 就是我们的程序需要访问的数据,例如图片、文本、视频、音频等等。

访问资源有两种方式:

  • Location dependent 位置相关
  • Location Independent 位置独立

🐾 5.2,Location dependent(位置相关)

所谓Location Dependent,就是我们对资源的访问方式受程序所在位置的影响。

例如,在Java中,使用本机绝对路径访问文件时,就是一种Location Dependent的访问方法,代码如下:

File file = new File("/root/project/resource/config.xml")

**注:**root 是项目的根路径。

如果项目中使用上述方式读取文件,当项目在其他目录或其他机器上部署和运行时,就需要修改上述代码中的文件路径,因此上述用法是LocationDependent的。

注意:

并不是说通过File类来访问资源一定是Location Dependent的,我们借助File也可以实现Location Independent的访问,例如我们可以给File构造器传入相对路径,这里的相对路径是相对于当前工作目录(System.getProperty(“user.dir”))的,所以如果要访问的资源是项目的一部分,File类搭配相对路径也可以实现Location Independent的访问。

☁ 5.3,Location Independent(位置无关)

实现Location Independent的资源读取最常用的就是Class或ClassLoader类中的如下方法:

  • URL getResource(String name)
  • InputStream getResourceAsStream(String name)
  • Enumeration<URL> getResources(String name)
  • getSystemResource, getSystemResources, getSystemResourceAsStream

其中,前两个方法是Class和ClassLoader类都有的,后面的方法只有ClassLoader类有。

借助这些方法,可以实现从classpath下读取资源,或者相对于当前class文件所在的目录读取资源。

Class 类获取资源的方法最终会调用ClassLoader类中对应的方法,那么,这两个类中获取资源的方法的区别在哪里呢?

区别在于ClassLoader类中的这两个方法仅支持相对于classpath的路径(开头不能加/,加了就获取不到classpath下的文件了),而Class类中的这两个方法除了支持相对于classpath的路径外(以/开头),还支持相对于当前class文件所在目录的路径(开头不加/)。
例子:

image-20230722134955576

public class GetResourceTest {
    public static void main(String[] args) {
        // 获取不到, 因为是相对于xxx/target/classes/com/resourcetest/的路径
        URL resource1 = GetResourceTest.class.getResource("config.xml");
        // 下面3个能获取到, 因为是相对于classpath的路径
        URL resource2 = GetResourceTest.class.getResource("/config.xml");
        URL resource3 = GetResourceTest.class.getClassLoader().getResource("config.xml");
        URL resource4 = GetResourceTest.class.getClassLoader().getResource("./config.xml");
        // 获取不到,无法被解析为相对于classpath的路径
        URL resource5 = GetResourceTest.class.getClassLoader().getResource("/config.xml");

        System.out.println(resource1); // null
        System.out.println(resource2); // 非null
        System.out.println(resource3); // 非null
        System.out.println(resource4); // 非null
        System.out.println(resource5); // null
    }
}
  • 15
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
package druidJDBCUtils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class DruidJDBCUtils { //定义成员变量 private static DataSource ds; //静态代码块加载配置文件 static { try { Properties prop = new Properties(); InputStream is = DruidJDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); prop.load(is); ds = DruidDataSourceFactory.createDataSource(prop); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取数据库连接对象 */ public static Connection getConnection() throws SQLException { return ds.getConnection(); } /** * 获取连接池方法 */ public static DataSource getDataSource(){ return ds; } /** * 关闭资源方法 * close()查询sql方法 */ public static void close(ResultSet resultSet, Statement statement, Connection connection) { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 关闭资源方法 * close()增删改sql方法 */ public static void close(Statement statement, Connection connection) {
### 回答1: getResourceAsStream() 是一个 Java 方法,用于从类路径中获取资源文件的 InputStream。这个方法通常在 Java 的 Class 类中使用,因为 Class 类是 Java 中所有类的父类,因此它可以代表任何一个 Java 类。 因此,getResourceAsStream() 方法可以在任何 Java 项目中的任何 Java 类中使用,只要该类位于类路径中。 ### 回答2: getResourceAsStreamJava中一个用于获取资源文件的方法。它是在java.lang.Class类中定义的。 具体来说,getResourceAsStream方法可以用于在类路径(classpath)中查找并获取指定文件名的资源文件。它返回一个InputStream对象,可以用于读取资源文件的内容。 getResourceAsStream方法的调用方式通常是通过Class对象进行调用,例如: InputStream inputStream = MyClass.class.getResourceAsStream("filename.txt"); 在这个例子中,MyClass是调用getResourceAsStream方法的类的名称,"filename.txt"是要获取的资源文件的名称。 getResourceAsStream方法在查找资源文件时遵循以下规则: 1. 如果文件名以'/'开头,则表示从classpath的根目录开始查找资源。 2. 如果文件名不以'/'开头,则表示从当前类的包路径开始查找资源。 如果在指定路径下找不到资源文件,getResourceAsStream会返回null。 总之,可以通过getResourceAsStream方法方便地获取Java项目中的资源文件,并且它的使用非常灵活和方便。 ### 回答3: getResourceAsStream方法是用于在Java程序中获取资源文件的输入流的方法。它位于java.lang.Class类中,可以通过Class类的实例对象调用。 getResourceAsStream方法默认从当前类所在的包中获取资源文件的输入流。如果资源文件与当前类位于同一个包中,则可以直接通过文件名获取输入流。例如,若资源文件名为"example.txt",当前类的包名为"com.example",则可以使用以下代码获取输入流: InputStream inputStream = MyClass.class.getResourceAsStream("example.txt"); 此时,getResourceAsStream方法会在"com.example"包中查找名为"example.txt"的资源文件,并返回其输入流。 如果资源文件不在当前类所在的包中,而是在其他包中,可以使用相对路径或绝对路径来指定资源文件的位置。 使用相对路径时,可以通过"../"来指定上一级目录。例如,若资源文件位于当前类所在包的上一级目录的"resources"文件夹中,可以使用以下代码获取输入流: InputStream inputStream = MyClass.class.getResourceAsStream("../resources/example.txt"); 使用绝对路径时,可以使用以"/"开头的路径来指定资源文件的位置。例如,若资源文件位于项目的根目录的"src/main/resources"文件夹中,可以使用以下代码获取输入流: InputStream inputStream = MyClass.class.getResourceAsStream("/src/main/resources/example.txt"); 需要注意的是,getResourceAsStream方法会返回资源文件的输入流,但不会返回文件的物理路径。 综上所述,getResourceAsStream方法可以用于在Java程序中获取资源文件的输入流,通过提供相对路径或绝对路径来指定资源文件的位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值