zoukankan      html  css  js  c++  java
  • SpringBoot项目构建成jar运行后,如何正确读取resource下的文件

    SpringBoot项目构建成jar运行后,如何正确读取resource下的文件

    不管你使用的是SpringBoot 1.x还是SpringBoot2.x,在开Dev环境中使用eclipse、IEAD、STS等IDE工具,进行resource目录下文件的获取,简单的采用@Value注解的形式就可以得到,文件读取的主知一般情况下也是没有问题的,比如

    File file = ResourceUtils.getFile("classpath:exceltmp/template_export.xls");
    

    度娘检索出来的文章也基本上告诉你,这样是没有问题的。But,使用mvn package构建成jar文件,运行后报异常如下:

    java.io.FileNotFoundException: class path resource [exceltmp/template_export.xls] cannot be resolved to absolute file path because it does not reside in the file system:jar:file:/Users/apple/project-code/xdod-project/xdod-backend/target/xdod-backend.jar!/BOOT-INF/classes!/exceltmp/template_export.xls
    

    Resource下的文件是存在于jar这个文件里面,在磁盘上是没有真实路径存在的,它其实是位于jar内部的一个路径。所以通过ResourceUtils.getFile或者this.getClass().getResource("")方法无法正确获取文件。

    有一种比较偷懒的做法:将文档放在项目外,应用可以读取到的一个固定目录。按正常的方式读取即可,但可维护性比较差,很容易被误操作丢失。

    文本文件读取

    这种情况下可以采用流的方式来读取文件,拿到文件流再进行相关的操作。如果你使用Spring框架的话,可以采用ClassPathResource来读取文件流,将文件读取成字符串才进行二次操作,比较适用于文本文件,如properties,txt,csv,SQL,json等,代码参考:

    String data = "";
    ClassPathResource cpr = new ClassPathResource("static/file.txt");
    try {
        byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
        data = new String(bdata, StandardCharsets.UTF_8);
    } catch (IOException e) {
        LOG.warn("IOException", e);
    }
    

    这里提供一个工具类来帮助大家读取文件:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.stream.Collectors;
    
    import org.springframework.core.io.ClassPathResource;
    
    public final class ClassPathResourceReader {
        /**
         * path:文件路径
         * @since JDK 1.8
         */
        private final String path;
    
        /**
         * content:文件内容
         * @since JDK 1.6
         */
        private String content;
    
        public ClassPathResourceReader(String path) {
            this.path = path;
        }
    
        public String getContent() {
            if (content == null) {
                try {
                    ClassPathResource resource = new ClassPathResource(path);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
                    content = reader.lines().collect(Collectors.joining("
    "));
                    reader.close();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
            return content;
        }
    }
    

    使用方式也是相当简单

    String content = new ClassPathResourceReader("log4j.properties").getContent();
    

    非文本文件读取

    更多的情况是读取非文本文件,比如xls,还是希望拿到一个文件,再去解析使用。参考代码如下:

    ClassPathResource classPathResource = new ClassPathResource("exceltmp/template_export.xls"");
    
    InputStream inputStream = classPathResource.getInputStream();
    //生成目标文件
    File somethingFile = File.createTempFile("template_export_copy", ".xls");
    try {
        FileUtils.copyInputStreamToFile(inputStream, somethingFile);
    } finally {
        IOUtils.closeQuietly(inputStream);
    }
    

    拿到目标文件后,再按照正常的取法如ResourceUtils.getFile,读取即可。

    参考文章:https://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as-jar

    获取更多内容请关注公众号
    在这里插入图片描述

    成长的乐趣,在于分享!
    大龄程序员,一路走来,感慨颇多。闲暇时写写字,希望能给同行人一点帮助。
    本文版权归作者growithus和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    【json的处理】一、Gson处理
    【校验处理】三、Spring Validation 校验处理
    【校验处理】二、SpringBoot Validate 统一处理
    【校验处理】一、Java Bean Validation验证
    div 固定宽高 水平垂直居中方法
    vue 修改ElementUI样式(非全局修改)
    js --- execCommand('copy')复制文本到剪切板换行符不生效
    C#枚举(一)使用总结以及扩展类分享
    php执行时长
    关于PHP的编码格式导致的乱码
  • 原文地址:https://www.cnblogs.com/growithus/p/11012153.html
Copyright © 2011-2022 走看看