简体   繁体   English

Spring Boot jar 中的 FileNotFoundException 但文件存在

[英]FileNotFoundException in spring boot jar but the file is present

I am getting FileNotFoundException while the file is clearly present in the jar.当文件明显存在于 jar 中时,我收到 FileNotFoundException。 why is it so?为什么会这样?

java.io.FileNotFoundException: file:/Users/serviceuser/project/coolApp/target/coolApp-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/ssl_certs/mysslstore.jks (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method) ~[na:na]
    at java.base/java.io.FileInputStream.open(FileInputStream.java:219) ~[na:na]
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157) ~[na:na]
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112) ~[na:na]

However, I see the files packaged in jar.但是,我看到打包在 jar 中的文件。

jar -tf coolApp-1.0-SNAPSHOT.jar | grep ssl

在此处输入图片说明

EDIT I load the file as following编辑我加载文件如下

new FileInputStream(CoolApp.class.getClassLoader().getResource("ssl_certs/mysslstore.jks").getFile())

Here :这里 :

new FileInputStream(CoolApp.class.getClassLoader().getResource("ssl_certs/mysslstore.jks").getFile());

getFile() is invoked on a URL included in a jar. getFile()在 jar 中包含的URL上调用。
As a result, it provides a particular File object since that is not a File directly accessible in the filesystem.因此,它提供了一个特定的File对象,因为它不是在File系统中可直接访问的File

And the URL javadoc confirms that (emphasis is mine) :并且URL javadoc确认(重点是我的):

Class URL represents a Uniform Resource Locator, a pointer to a "resource" on the World Wide Web.类 URL 表示统一资源定位符,即指向万维网上“资源”的指针。 A resource can be something as simple as a file or a directory, or it can be a reference to a more complicated object, such as a query to a database or to a search engine .资源可以是简单的文件或目录,也可以是对更复杂对象的引用,例如对数据库或搜索引擎的查询

So the FileInputStream(File) constructor cannot necessarily be able to open that "special" file :所以FileInputStream(File)构造函数不一定能够打开那个“特殊”文件:

A FileInputStream obtains input bytes from a file in a file system. FileInputStream 从文件系统中的文件中获取输入字节。 What files are available depends on the host environment.哪些文件可用取决于主机环境。

You can compare what you try to do with the following :您可以将您尝试执行的操作与以下内容进行比较:

new FileInputStream("/Users/serviceuser/project/coolApp/target/coolApp-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/ssl_certs/mysslstore.jks")

As you guessed, the file included in the jar( mysslstore.jks ) could not be resolved by the OS filesystem.正如您所猜测的,操作系统文件系统无法解析 jar( mysslstore.jks ) 中包含的文件。

Instead of, use getResourceAsStream() that returns an input stream.而不是使用返回输入流的getResourceAsStream() That input stream refers to the bytes sequence represented by the resource.该输入流指的是由资源表示的字节序列。 In this way, the client code doesn't depend any longer on the way which the resource is stored.这样,客户端代码不再依赖于资源的存储方式。

InputStream is = CoolApp.class.getClassLoader().getResourceAsStream("ssl_certs/mysslstore.jks"));

像这样的文件需要在资源目录中。

I was facing the same issue in spring boot and I have tried many things like bellow but nun of them is working. thease all are working locally but  It is giving FileNotFoundException in dev environmnet because when we build a JAR, the resources get placed into the root directory of the packaged artifacts and our downloaded files I placed inside resource folder. 

Method 1: Working solution for jars
InputStream stram=getClass().getClassLoader().getResourceAsStream(File.separator+"database.properties");
URL url = getClass().getClassLoader().getResource(File.separator+"database.properties");

Only thing which worked is ResourceLoader. Need to Autowire it:
    @Autowired
    ResourceLoader resourceLoader;

        Resource resource = resourceLoader.getResource("classpath:" + File.separatorChar + NPIConstants.VAR_FOLDER
                + File.separatorChar + NPIConstants.TPSPIDsBUCKET_FILENAME);
        InputStreamResource isResource = new InputStreamResource(resource.getInputStream());

Method 1: Not Working solution for jars
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("database.properties");
System.out.println(is.available());

Method 2:  Not Working solution for jars
Resource resource = new ClassPathResource("database.properties");
InputStream input = resource.getInputStream();

Method 3: Not Working solution for jars
File file = new File("resources/database.properties");
String absolutePath = file.getAbsolutePath();

Method 4: Not Working solution for jars
File file = new File(getClass().getClassLoader().getResource("database.properties").getFile());

Method 5: Not Working solution for jars
ClassLoader classLoader = getClass().getClassLoader();
classLoader.getResource("database.properties");
String path  = classLoader.getResource("database.properties").getPath();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM