我想读取一个XML文件,它位于我的类路径中包含的jar之一中。我如何读取包含在jar中的任何文件?
jar
nx7onnlm1#
如果要从应用程序内部读取该文件,请用途:
InputStream input = getClass().getResourceAsStream("/classpath/to/my/file");
路径以“/"开头,但这不是文件系统中的路径,而是类路径中的路径,所以如果你的文件在类路径“org.xml”中,名为myxml.xml,路径看起来像“/org/xml/myxml.xml”。InputStream读取文件的内容。如果需要,您可以将其 Package 到Reader中。
jbose2ul2#
啊,这是我最喜欢的主题之一。基本上有两种方法可以通过类路径加载资源:
Class.getResourceAsStream(resource)
以及
ClassLoader.getResourceAsStream(resource)
(还有其他方法,包括以类似的方式获取资源的URL,然后打开到它的连接,但这是两种直接的方法)。第一个方法实际上委托给了第二个方法,在对资源名进行了修饰之后。资源名基本上有两种:绝对路径(例如“/path/to/resource/resource”)和相对路径(例如“resource”)。绝对路径以“/"开头。下面是一个示例。考虑一个类com.example.A。考虑两个资源,一个位于类路径中的/com/example/nested,另一个位于/top。下面的程序显示了访问这两个资源的九种可能的方法:
package com.example; public class A { public static void main(String args[]) { // Class.getResourceAsStream Object resource = A.class.getResourceAsStream("nested"); System.out.println("1: A.class nested=" + resource); resource = A.class.getResourceAsStream("/com/example/nested"); System.out.println("2: A.class /com/example/nested=" + resource); resource = A.class.getResourceAsStream("top"); System.out.println("3: A.class top=" + resource); resource = A.class.getResourceAsStream("/top"); System.out.println("4: A.class /top=" + resource); // ClassLoader.getResourceAsStream ClassLoader cl = A.class.getClassLoader(); resource = cl.getResourceAsStream("nested"); System.out.println("5: cl nested=" + resource); resource = cl.getResourceAsStream("/com/example/nested"); System.out.println("6: cl /com/example/nested=" + resource); resource = cl.getResourceAsStream("com/example/nested"); System.out.println("7: cl com/example/nested=" + resource); resource = cl.getResourceAsStream("top"); System.out.println("8: cl top=" + resource); resource = cl.getResourceAsStream("/top"); System.out.println("9: cl /top=" + resource); } }
程序的输出为:
1: A.class nested=java.io.BufferedInputStream@19821f 2: A.class /com/example/nested=java.io.BufferedInputStream@addbf1 3: A.class top=null 4: A.class /top=java.io.BufferedInputStream@42e816 5: cl nested=null 6: cl /com/example/nested=null 7: cl com/example/nested=java.io.BufferedInputStream@9304b1 8: cl top=java.io.BufferedInputStream@190d11 9: cl /top=null
大多数情况下,情况3会失败,因为类相对解析是相对于类的,所以“top”表示“/com/example/top”,但“/top”表示它所表示的内容。因为类加载器相对解析是相对于类加载器的,所以Case-5失败。但是,出乎意料的是,Case-6也失败了:一个人可能期望“/com/example/nested”正确解析。2要通过类加载器访问嵌套资源,你需要使用Case-7,也就是说嵌套路径相对于类加载器的根。3同样的,Case-9失败,但是Case-8通过。记住:对于java.lang.Class,getResourceAsStream()确实委托给类加载器:
public InputStream getResourceAsStream(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResourceAsStream(name); } return cl.getResourceAsStream(name); }
所以resolveName()的行为才是重要的。最后,由于加载类的类加载器的行为本质上控制getResourceAsStream(),并且类加载器通常是定制加载器,则资源加载规则可能甚至更复杂。例如,对于Web应用,从Web应用的上下文中的WEB-INF/classes或WEB-INF/lib加载,而不是从隔离的其它Web应用加载。此外,行为良好的类加载器委托给父类,因此类路径中的重复资源可能无法使用此机制访问。
gz5pxeao3#
首先检查你的类加载器。
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = Class.class.getClassLoader(); } classLoader.getResourceAsStream("xmlFileNameInJarFile.xml"); // xml file location at xxx.jar // + folder // + folder // xmlFileNameInJarFile.xml
jdgnovmf4#
JAR基本上是一个ZIP文件,所以要这样对待它。下面是一个例子,说明如何从WAR文件中提取一个文件(也把它当作一个ZIP文件),并输出字符串内容。对于二进制文件,你需要修改提取过程,但有很多这样的例子。
public static void main(String args[]) { String relativeFilePath = "style/someCSSFile.css"; String zipFilePath = "/someDirectory/someWarFile.war"; String contents = readZipFile(zipFilePath,relativeFilePath); System.out.println(contents); } public static String readZipFile(String zipFilePath, String relativeFilePath) { try { ZipFile zipFile = new ZipFile(zipFilePath); Enumeration<? extends ZipEntry> e = zipFile.entries(); while (e.hasMoreElements()) { ZipEntry entry = (ZipEntry) e.nextElement(); // if the entry is not directory and matches relative file then extract it if (!entry.isDirectory() && entry.getName().equals(relativeFilePath)) { BufferedInputStream bis = new BufferedInputStream( zipFile.getInputStream(entry)); // Read the file // With Apache Commons I/O String fileContentsStr = IOUtils.toString(bis, "UTF-8"); // With Guava //String fileContentsStr = new String(ByteStreams.toByteArray(bis),Charsets.UTF_8); // close the input stream. bis.close(); return fileContentsStr; } else { continue; } } } catch (IOException e) { logger.error("IOError :" + e); e.printStackTrace(); } return null; }
在本例中,我使用的是Apache Commons I/O,如果您使用的是Maven,则依赖关系如下:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
r9f1avp55#
为了完整起见,最近在Jython邮件列表上有一个question,其中一个答案引用了这个线程。问题是如何从Jython中调用包含在.jar文件中的Python脚本,建议的答案如下所示(上面的答案之一解释了“InputStream”:
PythonInterpreter.execfile(InputStream)
2cmtqfgy6#
这也适用于Spring
ClassPathResource resource = new ClassPathResource("/file.txt", MainApplication.class); //resources folder InputStream inputStream = resource.getInputStream(); File file = new File("file.txt"); FileUtils.copyInputStreamToFile(inputStream, file);
6条答案
按热度按时间nx7onnlm1#
如果要从应用程序内部读取该文件,请用途:
路径以“/"开头,但这不是文件系统中的路径,而是类路径中的路径,所以如果你的文件在类路径“org.xml”中,名为myxml.xml,路径看起来像“/org/xml/myxml.xml”。
InputStream读取文件的内容。如果需要,您可以将其 Package 到Reader中。
jbose2ul2#
啊,这是我最喜欢的主题之一。基本上有两种方法可以通过类路径加载资源:
以及
(还有其他方法,包括以类似的方式获取资源的URL,然后打开到它的连接,但这是两种直接的方法)。
第一个方法实际上委托给了第二个方法,在对资源名进行了修饰之后。资源名基本上有两种:绝对路径(例如“/path/to/resource/resource”)和相对路径(例如“resource”)。绝对路径以“/"开头。
下面是一个示例。考虑一个类com.example.A。考虑两个资源,一个位于类路径中的/com/example/nested,另一个位于/top。下面的程序显示了访问这两个资源的九种可能的方法:
程序的输出为:
大多数情况下,情况3会失败,因为类相对解析是相对于类的,所以“top”表示“/com/example/top”,但“/top”表示它所表示的内容。
因为类加载器相对解析是相对于类加载器的,所以Case-5失败。但是,出乎意料的是,Case-6也失败了:一个人可能期望“/com/example/nested”正确解析。2要通过类加载器访问嵌套资源,你需要使用Case-7,也就是说嵌套路径相对于类加载器的根。3同样的,Case-9失败,但是Case-8通过。
记住:对于java.lang.Class,getResourceAsStream()确实委托给类加载器:
所以resolveName()的行为才是重要的。
最后,由于加载类的类加载器的行为本质上控制getResourceAsStream(),并且类加载器通常是定制加载器,则资源加载规则可能甚至更复杂。例如,对于Web应用,从Web应用的上下文中的WEB-INF/classes或WEB-INF/lib加载,而不是从隔离的其它Web应用加载。此外,行为良好的类加载器委托给父类,因此类路径中的重复资源可能无法使用此机制访问。
gz5pxeao3#
首先检查你的类加载器。
jdgnovmf4#
JAR基本上是一个ZIP文件,所以要这样对待它。下面是一个例子,说明如何从WAR文件中提取一个文件(也把它当作一个ZIP文件),并输出字符串内容。对于二进制文件,你需要修改提取过程,但有很多这样的例子。
在本例中,我使用的是Apache Commons I/O,如果您使用的是Maven,则依赖关系如下:
r9f1avp55#
为了完整起见,最近在Jython邮件列表上有一个question,其中一个答案引用了这个线程。
问题是如何从Jython中调用包含在.jar文件中的Python脚本,建议的答案如下所示(上面的答案之一解释了“InputStream”:
2cmtqfgy6#
这也适用于Spring