如何获取Java JAR文件中资源的path
我试图find一个资源的path,但我没有运气。
这可以工作(在IDE和JAR中),但这种方式我不能得到一个文件的path,只有文件的内容:
ClassLoader classLoader = getClass().getClassLoader(); PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));
如果我这样做:
ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("config/netclient.p").getFile());
结果是: java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
有没有办法获得一个资源文件的path?
这是故意的。 “文件”的内容可能不能用作文件。 请记住,您正在处理可能是JAR文件或其他types资源的一部分的类和资源。 类加载器不必为资源提供文件句柄,例如jar文件可能没有被扩展到文件系统中的单个文件中。
通过获取java.io.File可以做的任何事情都可以通过将stream复制到一个临时文件中来完成,如果java.io.File是绝对必要的。
加载资源时请确保您注意到以下区别:
getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path
和
getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning
我猜,这种混淆在加载资源时造成了大部分的问题。 加载图片时,使用getResourceAsStream()
更容易:
BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));
当你真的需要从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!"); }
我花了一段时间解决这个问题,因为没有解决scheme,我发现实际上工作,很奇怪! 工作目录经常不是JAR的目录,特别是如果从Windows下的“开始”菜单运行JAR(或任何程序)。 所以这就是我所做的,它适用于从JAR外部运行的.class文件,以及它适用于JAR。 (我只在Windows 7下testing过)
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. }
一条线的答案是 –
String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()
基本上getResource
方法给出的URL。 从这个URL你可以通过调用toExternalForm()
来提取path
参考文献:
getResource() , toExternalForm()
如果netclient.p
位于JAR文件中,则不会有path,因为该文件位于其他文件中。 在这种情况下,您可以拥有的最佳path实际上是file:/path/to/jarfile/bot.jar!/config/netclient.p
。
您需要了解jar文件中的path。
只要相对参照。 所以如果你有一个文件(myfile.txt),位于\src\main\resources
目录(maven style)下的foo.jar中。 你可以参考它:
src/main/resources/myfile.txt
如果你使用jar -tvf myjar.jar
转储你的jar,你会在jar文件中看到输出和相对path,并使用FORWARD SLASHES。
文件是文件系统中文件的抽象,文件系统不知道什么是JAR的内容。
尝试使用URI,我认为有一个jar://协议可能对你的purpouse有用。
这是来自用户Tombart的stream清除和closures的代码,以避免从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()); }
在我的情况下,我使用了一个URL对象,而不是path。
文件
File file = new File("my_path"); URL url = file.toURI().toURL();
使用classloader的类path中的资源
URL url = MyClass.class.getClassLoader().getResource("resource_name")
当我需要阅读内容时,我可以使用下面的代码:
InputStream stream = url.openStream();
您可以使用InputStream访问内容。
这就是说,不是加载资源的最佳方法,但是如果你绝对必须有java.io.File
引用,那么请尝试下面的代码:
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 }
这给你一个java.net.URL
,它可以在java.io.File
构造函数中使用。
以下path适用于我: classpath:/path/to/resource/in/jar
private static final String FILE_LOCATION = "com/input/file/somefile.txt"; //Method Body InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);
从getSystemResourceAsStream
获取这是最好的select。 通过获取inputstream而不是文件或URL,可以在JAR文件中独立运行。
在jar文件中时,资源绝对位于包层次结构(而不是文件系统层次结构)中。 所以如果你有类com.example.Sweet加载一个名为“./default.conf”的资源,那么这个资源的名字被指定为“/com/example/default.conf”。
但如果它在一个jar子里,那么它不是一个文件…
在你的jar文件夹(java / main / resources)里面添加你的文件(假设你已经添加了一个名为imports.xml的xml文件),然后你注入ResourceLoader
如果你使用spring
@Autowired private ResourceLoader resourceLoader;
里面的游览function写下列代码以加载文件:
Resource resource = resourceLoader.getResource("classpath:imports.xml"); try{ File file; file = resource.getFile();//will load the file ... }catch(IOException e){e.printStackTrace();}