如何在Java中从jar读取文件?
我想读取位于我的类路径中包含的jar
之一的XML文件。 我怎样才能读取包含在jar
中的任何文件?
如果你想从你的应用程序中读取这个文件,使用:
InputStream input = getClass().getResourceAsStream("/classpath/to/my/file");
路径以“/”开头,但不是文件系统中的路径,而是类路径中的路径。 因此,如果您的文件位于classpath“org.xml”并且名为myxml.xml,那么您的路径看起来像“/org/xml/myxml.xml”。
InputStream读取文件的内容。 如果你愿意的话,你可以把它换成一个阅读器。
我希望有帮助。
啊,这是我最喜欢的科目之一。 基本上有两种方法可以通过类路径加载资源:
Class.getResourceAsStream(resource)
和
ClassLoader.getResourceAsStream(resource)
(还有其他一些方法,包括以类似的方式获取资源的URL,然后打开一个连接,但这是两个直接的方式)。
第一个方法实际上委托给第二个,在修改资源名称之后。 基本上有两种资源名称:绝对的(例如“/ path / to / resource / resource”)和相对的(例如“resource”)。 绝对路径以“/”开头。
这是一个应该说明的例子。 考虑一个类com.example.A。 考虑两个资源,一个位于/ com / example / nested,另一个位于/ top,位于classpath中。 以下程序显示了九种可能的方式来访问这两个资源:
包com.example; 公开课A { 公共静态无效的主要(字符串参数[]){ // 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嵌套= 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
大部分事情都是你所期望的。 第三种情况是因为类相对于类的解析失败,所以“top”的意思是“/ com / example / top”,而“/ top”是指它的意思。
情况5失败是因为类加载器相对于类加载器的解析。 但是,意外的情况6也失败了:人们可能期望“/ com / example / nested”来正确解析。 要通过类加载器访问嵌套的资源,您需要使用Case-7,即嵌套路径相对于类加载器的根。 同样,案例9失败,但案例8通过。
记住:对于java.lang.Class,getResourceAsStream()确实委托给类加载器:
public InputStream getResourceAsStream(String name){ name = resolveName(name); ClassLoader cl = getClassLoader0(); if(cl == null){ //系统类 返回ClassLoader.getSystemResourceAsStream(name); } 返回cl.getResourceAsStream(name); }
所以resolveName()的行为是重要的。
最后,由于类加载器的行为加载了本质上控制着getResourceAsStream()的类,并且类加载器通常是自定义加载器,所以资源加载规则可能更加复杂。 例如对于Web应用程序,在Web应用程序的上下文中从WEB-INF / classes或WEB-INF / lib加载,而不是从隔离的其他web应用程序加载。 此外,行为良好的类加载器委托给父项,以便使用此机制可以不可访问类路径中的重复资源。
首先检查你的类加载器。
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
一个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>
为了完整起见,最近有一个关于Jython邮件列表的问题 ,其中一个答案提到了这个线程。
问题是如何从Jython中调用包含在.jar文件中的Python脚本,建议的答案如下(在上面的答案中解释为“InputStream”:
PythonInterpreter.execfile(InputStream)