如何在Java JAR文件中找到资源的路径?

时间:2021-01-23 17:14:25

I am trying to get a path to a Resource but I have had no luck.

我正试图找到一条通往资源的道路,但我运气不佳。

This works (both in IDE and with the JAR) but this way I can't get a path to a file, only the file contents:

这个方法(在IDE和JAR中都有),但是这样我就不能找到一个文件的路径,只有文件内容:

ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));

If I do this:

如果我这样做:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());

The result is: java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

结果是:. io .FileNotFoundException:文件:/道路/ /使用jarfile / bot.jar ! / config / netclient。p(无此文件或目录)

Is there a way to get a path to a resource file?

是否有办法获取资源文件的路径?

14 个解决方案

#1


63  

This is deliberate. The contents of the "file" may not be available as a file. Remember you are dealing with classes and resources that may be part of a JAR file or other kind of resource. The classloader does not have to provide a file handle to the resource, for example the jar file may not have been expanded into individual files in the file system.

这是故意的。“文件”的内容可能不能作为文件可用。记住,您正在处理的类和资源可能是JAR文件或其他类型资源的一部分。类加载器不需要向资源提供文件句柄,例如jar文件可能没有扩展到文件系统中的单个文件。

Anything you can do by getting a java.io.File could be done by copying the stream out into a temporary file and doing the same, if a java.io.File is absolutely necessary.

通过java.io来做任何事情。可以通过将流复制到一个临时文件并执行相同的操作(如果java.io)完成。文件是绝对必要的。

#2


40  

When loading a resource make sure you notice the difference between:

在加载资源时,请确保注意到以下区别:

getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path

and

getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning

I guess, this confusion is causing most of problems when loading a resource.

我想,这种混淆在加载资源时造成了大多数问题。


Also, when you're loading an image it's easier to use getResourceAsStream():

另外,当你加载一个图像时,使用getresourceflow()更容易:

BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));

When you really have to load a (non-image) file from a JAR archive, you might try this:

当您确实需要从JAR存档加载一个(非图像)文件时,您可以尝试以下方法:

    File file = null;
    String resource = "/com/myorg/foo.xml";
    URL res = getClass().getResource(resource);
    if (res.toString().startsWith("jar:")) {
        try {
            InputStream input = getClass().getResourceAsStream(resource);
            file = File.createTempFile("tempfile", ".tmp");
            OutputStream out = new FileOutputStream(file);
            int read;
            byte[] bytes = new byte[1024];

            while ((read = input.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            file.deleteOnExit();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    } else {
        //this will probably work in your IDE, but not from a JAR
        file = new File(res.getFile());
    }

    if (file != null && !file.exists()) {
        throw new RuntimeException("Error: File " + file + " not found!");
    }

#3


18  

The one line answer is -

唯一的答案是-。

String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()

Basically getResource method gives the URL. From this URL you can extract the path by calling toExternalForm()

getResource方法提供了URL。从这个URL可以通过调用toExternalForm()来提取路径

References:

引用:

getResource(), toExternalForm()

toExternalForm getResource()()

#4


12  

I spent a while messing around with this problem, because no solution I found actually worked, strangely enough! The working directory is frequently not the directory of the JAR, especially if a JAR (or any program, for that matter) is run from the Start Menu under Windows. So here is what I did, and it works for .class files run from outside a JAR just as well as it works for a JAR. (I only tested it under Windows 7.)

我花了一段时间来解决这个问题,因为我发现没有一个解决方案是有效的,奇怪的是!工作目录通常不是JAR的目录,特别是如果一个JAR(或者任何程序)是从Windows下的开始菜单中运行的。这就是我所做的,它适用于。类文件从一个罐子外面运行,就像它对一个罐子一样有效。(我只在Windows 7下测试过。)

try {
    //Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
    //Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
    //Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
    PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.

    //Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
    try {
        PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
    } catch (Exception e) { }

    //Find the last / and cut it off at that location.
    PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
    //If it starts with /, cut it off.
    if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
    //If it starts with file:/, cut that off, too.
    if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
    PROGRAM_DIRECTORY = ""; //Current working directory instead.
}

#5


7  

if netclient.p is inside a JAR file, it won't have a path because that file is located inside other file. in that case, the best path you can have is really file:/path/to/jarfile/bot.jar!/config/netclient.p.

如果netclient。p在JAR文件中,它不会有路径,因为该文件位于其他文件中。在这种情况下,您所能拥有的最好的路径就是文件:/path/to/jarfile/bo .jar!/config/netclient.p。

#6


6  

You need to understand the path within the jar file.
Simply refer to it relative. So if you have a file (myfile.txt), located in foo.jar under the \src\main\resources directory (maven style). You would refer to it like:

您需要了解jar文件中的路径。简单地说它是相对的。如果你有一个文件(myfile.txt),位于foo。jar在\src\ \主\资源目录下(maven样式)。你会说:

src/main/resources/myfile.txt

If you dump your jar using jar -tvf myjar.jar you will see the output and the relative path within the jar file, and use the FORWARD SLASHES.

如果你使用jar -tvf myjar来转储你的jar。您将在jar文件中看到输出和相对路径,并使用前斜杠。

#7


2  

A File is an abstraction for a file in a filesystem, and the filesystems don't know anything about what are the contents of a JAR.

文件是文件系统中的文件的抽象,而文件系统对JAR的内容一无所知。

Try with an URI, I think there's a jar:// protocol that might be useful for your purpouses.

尝试使用一个URI,我认为有一个jar://协议可能对您的purp有用。

#8


2  

This is same code from user Tombart with stream flush and close to avoid incomplete temporary file content copy from jar resource and to have unique temp file names.

这是来自用户Tombart的相同代码,它使用流刷新和关闭,以避免jar资源中不完整的临时文件内容拷贝,并具有惟一的临时文件名称。

     File file = null;
        String resource = "/view/Trial_main.html" ;
        URL res = getClass().getResource(resource);
        if (res.toString().startsWith("jar:")) {
            try {
                InputStream input = getClass().getResourceAsStream(resource);
                file = File.createTempFile(new Date().getTime()+"", ".html");
                OutputStream out = new FileOutputStream(file);
                int read;
                byte[] bytes = new byte[1024];

                while ((read = input.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }
                out.flush();
                out.close();
                input.close();
                file.deleteOnExit();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } else {
            //this will probably work in your IDE, but not from a JAR
            file = new File(res.getFile());
        }

#9


2  

In my case, I have used a URL object instead Path.

在我的例子中,我使用了一个URL对象来替代路径。

File

文件

File file = new File("my_path");
URL url = file.toURI().toURL();

Resource in classpath using classloader

使用类加载器的类路径资源。

URL url = MyClass.class.getClassLoader().getResource("resource_name")

When I need to read the content, I can use the following code:

当我需要阅读内容时,我可以使用以下代码:

InputStream stream = url.openStream();

And you can access the content using an InputStream.

您可以使用InputStream访问该内容。

#10


1  

This is, at it has been stated, not the optimal way to load resources, but if you absolutely must have a java.io.File reference, then try following:

这是说,这不是加载资源的最佳方式,但如果您绝对必须拥有java.io。文件引用,然后尝试:

 URL url = null;
  try {
     URL baseUrl = YourClass.class.getResource(".");
     if (baseUrl != null) {
        url = new URL(baseUrl, "yourfilename.ext");
     } else {
        url = YourClass.class.getResource("yourfilename.ext");
     }
  } catch (MalformedURLException e) {
     // Do something appropriate
  }

This gives you a java.net.URL and it can be used in a java.io.File constructor.

这给您一个java.net.URL,它可以在java.io中使用。文件的构造函数。

#11


1  

The following path worked for me: classpath:/path/to/resource/in/jar

下面的路径适合我:类路径:/path/to/resource/in/jar。

#12


1  

private static final String FILE_LOCATION = "com/input/file/somefile.txt";

//Method Body


InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);

Getting this from getSystemResourceAsStream is the best option. By getting the inputstream rather than the file or the URL, works in a JAR file and as stand alone.

从getsystemresourementstream获得这个是最好的选择。通过获取inputstream而不是文件或URL,可以在JAR文件中工作,并且可以独立运行。

#13


0  

When in a jar file, the resource is located absolutely in the package hierarchy (not file system hierarchy). So if you have class com.example.Sweet loading a resource named "./default.conf" then the resource's name is specified as "/com/example/default.conf".

在jar文件中,资源完全位于包层次结构(而不是文件系统层次结构)中。如果你有类com.example。加载名为“./default”的资源。然后,将资源的名称指定为“/com/example/default.conf”。

But if it's in a jar then it's not a File ...

但是如果它在一个罐子里,那么它就不是一个文件……

#14


0  

Inside your ressources folder (java/main/resources) of your jar add your file (we assume that you have added an xml file named imports.xml), after that you inject ResourceLoader if you use spring like bellow

在您的jar的ressources文件夹(java/main/resources)中添加您的文件(我们假定您已经添加了一个名为imports.xml的xml文件),然后在您使用像bellow这样的spring时注入ResourceLoader。

@Autowired
private ResourceLoader resourceLoader;

inside tour function write the bellow code in order to load file:

内部漫游函数编写bellow代码来加载文件:

    Resource resource = resourceLoader.getResource("classpath:imports.xml");
    try{
        File file;
        file = resource.getFile();//will load the file
...
    }catch(IOException e){e.printStackTrace();}

#1


63  

This is deliberate. The contents of the "file" may not be available as a file. Remember you are dealing with classes and resources that may be part of a JAR file or other kind of resource. The classloader does not have to provide a file handle to the resource, for example the jar file may not have been expanded into individual files in the file system.

这是故意的。“文件”的内容可能不能作为文件可用。记住,您正在处理的类和资源可能是JAR文件或其他类型资源的一部分。类加载器不需要向资源提供文件句柄,例如jar文件可能没有扩展到文件系统中的单个文件。

Anything you can do by getting a java.io.File could be done by copying the stream out into a temporary file and doing the same, if a java.io.File is absolutely necessary.

通过java.io来做任何事情。可以通过将流复制到一个临时文件并执行相同的操作(如果java.io)完成。文件是绝对必要的。

#2


40  

When loading a resource make sure you notice the difference between:

在加载资源时,请确保注意到以下区别:

getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path

and

getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning

I guess, this confusion is causing most of problems when loading a resource.

我想,这种混淆在加载资源时造成了大多数问题。


Also, when you're loading an image it's easier to use getResourceAsStream():

另外,当你加载一个图像时,使用getresourceflow()更容易:

BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));

When you really have to load a (non-image) file from a JAR archive, you might try this:

当您确实需要从JAR存档加载一个(非图像)文件时,您可以尝试以下方法:

    File file = null;
    String resource = "/com/myorg/foo.xml";
    URL res = getClass().getResource(resource);
    if (res.toString().startsWith("jar:")) {
        try {
            InputStream input = getClass().getResourceAsStream(resource);
            file = File.createTempFile("tempfile", ".tmp");
            OutputStream out = new FileOutputStream(file);
            int read;
            byte[] bytes = new byte[1024];

            while ((read = input.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            file.deleteOnExit();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    } else {
        //this will probably work in your IDE, but not from a JAR
        file = new File(res.getFile());
    }

    if (file != null && !file.exists()) {
        throw new RuntimeException("Error: File " + file + " not found!");
    }

#3


18  

The one line answer is -

唯一的答案是-。

String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()

Basically getResource method gives the URL. From this URL you can extract the path by calling toExternalForm()

getResource方法提供了URL。从这个URL可以通过调用toExternalForm()来提取路径

References:

引用:

getResource(), toExternalForm()

toExternalForm getResource()()

#4


12  

I spent a while messing around with this problem, because no solution I found actually worked, strangely enough! The working directory is frequently not the directory of the JAR, especially if a JAR (or any program, for that matter) is run from the Start Menu under Windows. So here is what I did, and it works for .class files run from outside a JAR just as well as it works for a JAR. (I only tested it under Windows 7.)

我花了一段时间来解决这个问题,因为我发现没有一个解决方案是有效的,奇怪的是!工作目录通常不是JAR的目录,特别是如果一个JAR(或者任何程序)是从Windows下的开始菜单中运行的。这就是我所做的,它适用于。类文件从一个罐子外面运行,就像它对一个罐子一样有效。(我只在Windows 7下测试过。)

try {
    //Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
    //Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
    //Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
    PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.

    //Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
    try {
        PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
    } catch (Exception e) { }

    //Find the last / and cut it off at that location.
    PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
    //If it starts with /, cut it off.
    if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
    //If it starts with file:/, cut that off, too.
    if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
    PROGRAM_DIRECTORY = ""; //Current working directory instead.
}

#5


7  

if netclient.p is inside a JAR file, it won't have a path because that file is located inside other file. in that case, the best path you can have is really file:/path/to/jarfile/bot.jar!/config/netclient.p.

如果netclient。p在JAR文件中,它不会有路径,因为该文件位于其他文件中。在这种情况下,您所能拥有的最好的路径就是文件:/path/to/jarfile/bo .jar!/config/netclient.p。

#6


6  

You need to understand the path within the jar file.
Simply refer to it relative. So if you have a file (myfile.txt), located in foo.jar under the \src\main\resources directory (maven style). You would refer to it like:

您需要了解jar文件中的路径。简单地说它是相对的。如果你有一个文件(myfile.txt),位于foo。jar在\src\ \主\资源目录下(maven样式)。你会说:

src/main/resources/myfile.txt

If you dump your jar using jar -tvf myjar.jar you will see the output and the relative path within the jar file, and use the FORWARD SLASHES.

如果你使用jar -tvf myjar来转储你的jar。您将在jar文件中看到输出和相对路径,并使用前斜杠。

#7


2  

A File is an abstraction for a file in a filesystem, and the filesystems don't know anything about what are the contents of a JAR.

文件是文件系统中的文件的抽象,而文件系统对JAR的内容一无所知。

Try with an URI, I think there's a jar:// protocol that might be useful for your purpouses.

尝试使用一个URI,我认为有一个jar://协议可能对您的purp有用。

#8


2  

This is same code from user Tombart with stream flush and close to avoid incomplete temporary file content copy from jar resource and to have unique temp file names.

这是来自用户Tombart的相同代码,它使用流刷新和关闭,以避免jar资源中不完整的临时文件内容拷贝,并具有惟一的临时文件名称。

     File file = null;
        String resource = "/view/Trial_main.html" ;
        URL res = getClass().getResource(resource);
        if (res.toString().startsWith("jar:")) {
            try {
                InputStream input = getClass().getResourceAsStream(resource);
                file = File.createTempFile(new Date().getTime()+"", ".html");
                OutputStream out = new FileOutputStream(file);
                int read;
                byte[] bytes = new byte[1024];

                while ((read = input.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }
                out.flush();
                out.close();
                input.close();
                file.deleteOnExit();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } else {
            //this will probably work in your IDE, but not from a JAR
            file = new File(res.getFile());
        }

#9


2  

In my case, I have used a URL object instead Path.

在我的例子中,我使用了一个URL对象来替代路径。

File

文件

File file = new File("my_path");
URL url = file.toURI().toURL();

Resource in classpath using classloader

使用类加载器的类路径资源。

URL url = MyClass.class.getClassLoader().getResource("resource_name")

When I need to read the content, I can use the following code:

当我需要阅读内容时,我可以使用以下代码:

InputStream stream = url.openStream();

And you can access the content using an InputStream.

您可以使用InputStream访问该内容。

#10


1  

This is, at it has been stated, not the optimal way to load resources, but if you absolutely must have a java.io.File reference, then try following:

这是说,这不是加载资源的最佳方式,但如果您绝对必须拥有java.io。文件引用,然后尝试:

 URL url = null;
  try {
     URL baseUrl = YourClass.class.getResource(".");
     if (baseUrl != null) {
        url = new URL(baseUrl, "yourfilename.ext");
     } else {
        url = YourClass.class.getResource("yourfilename.ext");
     }
  } catch (MalformedURLException e) {
     // Do something appropriate
  }

This gives you a java.net.URL and it can be used in a java.io.File constructor.

这给您一个java.net.URL,它可以在java.io中使用。文件的构造函数。

#11


1  

The following path worked for me: classpath:/path/to/resource/in/jar

下面的路径适合我:类路径:/path/to/resource/in/jar。

#12


1  

private static final String FILE_LOCATION = "com/input/file/somefile.txt";

//Method Body


InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);

Getting this from getSystemResourceAsStream is the best option. By getting the inputstream rather than the file or the URL, works in a JAR file and as stand alone.

从getsystemresourementstream获得这个是最好的选择。通过获取inputstream而不是文件或URL,可以在JAR文件中工作,并且可以独立运行。

#13


0  

When in a jar file, the resource is located absolutely in the package hierarchy (not file system hierarchy). So if you have class com.example.Sweet loading a resource named "./default.conf" then the resource's name is specified as "/com/example/default.conf".

在jar文件中,资源完全位于包层次结构(而不是文件系统层次结构)中。如果你有类com.example。加载名为“./default”的资源。然后,将资源的名称指定为“/com/example/default.conf”。

But if it's in a jar then it's not a File ...

但是如果它在一个罐子里,那么它就不是一个文件……

#14


0  

Inside your ressources folder (java/main/resources) of your jar add your file (we assume that you have added an xml file named imports.xml), after that you inject ResourceLoader if you use spring like bellow

在您的jar的ressources文件夹(java/main/resources)中添加您的文件(我们假定您已经添加了一个名为imports.xml的xml文件),然后在您使用像bellow这样的spring时注入ResourceLoader。

@Autowired
private ResourceLoader resourceLoader;

inside tour function write the bellow code in order to load file:

内部漫游函数编写bellow代码来加载文件:

    Resource resource = resourceLoader.getResource("classpath:imports.xml");
    try{
        File file;
        file = resource.getFile();//will load the file
...
    }catch(IOException e){e.printStackTrace();}