如何在Java中从jar读取文件?
我想读取一个XML文件,该文件位于类路径中包含的一个JAR中。如何读取jar中包含的任何文件?如果要从应用程序内部读取该文件,请使用:如何在Java中从jar读取文件?,java,file-io,jar,Java,File Io,Jar,我想读取一个XML文件,该文件位于类路径中包含的一个JAR中。如何读取jar中包含的任何文件?如果要从应用程序内部读取该文件,请使用: InputStream input = getClass().getResourceAsStream("/classpath/to/my/file"); 路径以/开头,但这不是文件系统中的路径,而是类路径中的路径。因此,如果您的文件位于classpath org.xml,并且名为myxml.xml,那么您的路径看起来像/org/xml/myxml.xml In
InputStream input = getClass().getResourceAsStream("/classpath/to/my/file");
路径以/开头,但这不是文件系统中的路径,而是类路径中的路径。因此,如果您的文件位于classpath org.xml,并且名为myxml.xml,那么您的路径看起来像/org/xml/myxml.xml
InputStream读取文件的内容。如果你愿意,你可以把它包装成阅读器
我希望这有帮助。啊,这是我最喜欢的科目之一。基本上有两种方法可以通过类路径加载资源: Class.getResourceAsStreamresource 及 ClassLoader.getResourceAsStreamresource 还有其他方法,包括以类似的方式获取资源的URL,然后打开与它的连接,但这是两种直接的方法 在弄乱资源名称后,第一个方法实际上委托给第二个方法。基本上有两种资源名称:绝对的,例如/path/to/resource/resource和相对的,例如资源。绝对路径以/开头 这里有一个例子可以说明。考虑一个类COM。考虑两个资源,一个位于/COM/示例/嵌套,另一个位于/Stof,在类路径中。以下程序显示了访问这两个资源的九种可能方式: 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表示它所说的内容 案例5失败,因为类加载器相对解析是关于类加载器的。但是,出乎意料的是,Case-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) { // A system class. return ClassLoader.getSystemResourceAsStream(name); } return cl.getResourceAsStream(name); } 因此,resolveName的行为很重要
最后,由于类装入器的行为本质上控制了getResourceAsStream,并且类装入器通常是一个自定义装入器,因此资源装入规则可能更加复杂。e、 g.对于Web应用程序,从Web应用程序上下文中的Web-INF/classes或Web-INF/lib加载,但不要从其他孤立的Web应用程序加载。此外,行为良好的类加载器将委托给父类,因此使用此机制可能无法访问类路径中的重复资源。JAR基本上是一个ZIP文件,因此请将其视为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)
这与我给出的答案基本相同,但解释得更详细+1这里有一个提到的resolveName方法:查看是否要从jar中的目录中读取文件,以及文件的编号,请参阅
PythonInterpreter.execfile(InputStream)