Java 如何从jar文件中读取文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2271926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to read a file from a jar file?
提问by Freeman
I have a file in a JAR file. It's 1.txt
, for example.
我在 JAR 文件中有一个文件。1.txt
例如,它是。
How can I access it? My source code is:
我怎样才能访问它?我的源代码是:
Double result=0.0;
File file = new File("1.txt")); //how get this file from a jar file
BufferedReader input = new BufferedReader(new FileReader(file));
String line;
while ((line = input.readLine()) != null) {
if(me==Integer.parseInt(line.split(":")[0])){
result= parseDouble(line.split(":")[1]);
}
}
input.close();
return result;
采纳答案by Sean Owen
You can't use File, since this file does not exist independently on the file system. Instead you need getResourceAsStream(), like so:
你不能使用 File,因为这个文件在文件系统上不是独立存在的。相反,您需要 getResourceAsStream(),如下所示:
...
InputStream in = getClass().getResourceAsStream("/1.txt");
BufferedReader input = new BufferedReader(new InputStreamReader(in));
...
回答by jjnguy
Something similar to this answeris what you need.
与此答案类似的东西正是您所需要的。
You need to pull the file out of the archive in that special way.
您需要以这种特殊方式将文件从存档中提取出来。
BufferedReader input = new BufferedReader(new InputStreamReader(
this.getClass().getClassLoader().getResourceAsStream("1.txt")));
回答by Bozho
If your jar is on the classpath:
如果您的 jar 位于类路径中:
InputStream is = YourClass.class.getResourceAsStream("1.txt");
If it is not on the classpath, then you can access it via:
如果它不在类路径上,那么您可以通过以下方式访问它:
URL url = new URL("jar:file:/absolute/location/of/yourJar.jar!/1.txt");
InputStream is = url.openStream();
回答by Buhake Sindi
A Jar file is a zip file.....
Jar 文件是一个 zip 文件.....
So to read a jar file, try
所以要读取 jar 文件,请尝试
ZipFile file = new ZipFile("whatever.jar");
if (file != null) {
ZipEntries entries = file.entries(); //get entries from the zip file...
if (entries != null) {
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
//use the entry to see if it's the file '1.txt'
//Read from the byte using file.getInputStream(entry)
}
}
}
Hope this helps.
希望这可以帮助。
回答by RickHigh
I have run into this same issue several times before. I was hoping in JDK 7 that someone would write a classpath filesystem, but alas not yet.
我以前多次遇到过同样的问题。我希望在 JDK 7 中有人会编写类路径文件系统,但可惜还没有。
Spring has the Resource class which allows you to load classpath resources quite nicely.
Spring 有 Resource 类,它允许您很好地加载类路径资源。
The answers have been very good, but I thought I could add to the discussion with showing an example that works with files and directories that are classpath resources.
答案非常好,但我想我可以通过展示一个示例来添加讨论,该示例适用于作为类路径资源的文件和目录。
I wrote a little prototype to solve this very problem. The prototype does not handle every edge case, but it does handle looking for resources in directories that are in the jar files.
我写了一个小原型来解决这个问题。该原型并不处理所有边缘情况,但它确实处理在 jar 文件中的目录中查找资源。
I have used Stack Overflow for quite sometime. This is the first time that I remember answering a question so forgive me if I go to long (it is my nature).
我使用 Stack Overflow 已经有一段时间了。这是我记得第一次回答问题,所以如果我做多请原谅我(这是我的本性)。
package com.foo;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Prototype resource reader.
* This prototype is devoid of error checking.
*
*
* I have two prototype jar files that I have setup.
* <pre>
* <dependency>
* <groupId>invoke</groupId>
* <artifactId>invoke</artifactId>
* <version>1.0-SNAPSHOT</version>
* </dependency>
*
* <dependency>
* <groupId>node</groupId>
* <artifactId>node</artifactId>
* <version>1.0-SNAPSHOT</version>
* </dependency>
* </pre>
* The jar files each have a file under /org/node/ called resource.txt.
* <br />
* This is just a prototype of what a handler would look like with classpath://
* I also have a resource.foo.txt in my local resources for this project.
* <br />
*/
public class ClasspathReader {
public static void main(String[] args) throws Exception {
/* This project includes two jar files that each have a resource located
in /org/node/ called resource.txt.
*/
/*
Name space is just a device I am using to see if a file in a dir
starts with a name space. Think of namespace like a file extension
but it is the start of the file not the end.
*/
String namespace = "resource";
//someResource is classpath.
String someResource = args.length > 0 ? args[0] :
//"classpath:///org/node/resource.txt"; It works with files
"classpath:///org/node/"; //It also works with directories
URI someResourceURI = URI.create(someResource);
System.out.println("URI of resource = " + someResourceURI);
someResource = someResourceURI.getPath();
System.out.println("PATH of resource =" + someResource);
boolean isDir = !someResource.endsWith(".txt");
/** Classpath resource can never really start with a starting slash.
* Logically they do, but in reality you have to strip it.
* This is a known behavior of classpath resources.
* It works with a slash unless the resource is in a jar file.
* Bottom line, by stripping it, it always works.
*/
if (someResource.startsWith("/")) {
someResource = someResource.substring(1);
}
/* Use the ClassLoader to lookup all resources that have this name.
Look for all resources that match the location we are looking for. */
Enumeration resources = null;
/* Check the context classloader first. Always use this if available. */
try {
resources =
Thread.currentThread().getContextClassLoader().getResources(someResource);
} catch (Exception ex) {
ex.printStackTrace();
}
if (resources == null || !resources.hasMoreElements()) {
resources = ClasspathReader.class.getClassLoader().getResources(someResource);
}
//Now iterate over the URLs of the resources from the classpath
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
/* if the resource is a file, it just means that we can use normal mechanism
to scan the directory.
*/
if (resource.getProtocol().equals("file")) {
//if it is a file then we can handle it the normal way.
handleFile(resource, namespace);
continue;
}
System.out.println("Resource " + resource);
/*
Split up the string that looks like this:
jar:file:/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar!/org/node/
into
this /Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar
and this
/org/node/
*/
String[] split = resource.toString().split(":");
String[] split2 = split[2].split("!");
String zipFileName = split2[0];
String sresource = split2[1];
System.out.printf("After split zip file name = %s," +
" \nresource in zip %s \n", zipFileName, sresource);
/* Open up the zip file. */
ZipFile zipFile = new ZipFile(zipFileName);
/* Iterate through the entries. */
Enumeration entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
/* If it is a directory, then skip it. */
if (entry.isDirectory()) {
continue;
}
String entryName = entry.getName();
System.out.printf("zip entry name %s \n", entryName);
/* If it does not start with our someResource String
then it is not our resource so continue.
*/
if (!entryName.startsWith(someResource)) {
continue;
}
/* the fileName part from the entry name.
* where /foo/bar/foo/bee/bar.txt, bar.txt is the file
*/
String fileName = entryName.substring(entryName.lastIndexOf("/") + 1);
System.out.printf("fileName %s \n", fileName);
/* See if the file starts with our namespace and ends with our extension.
*/
if (fileName.startsWith(namespace) && fileName.endsWith(".txt")) {
/* If you found the file, print out
the contents fo the file to System.out.*/
try (Reader reader = new InputStreamReader(zipFile.getInputStream(entry))) {
StringBuilder builder = new StringBuilder();
int ch = 0;
while ((ch = reader.read()) != -1) {
builder.append((char) ch);
}
System.out.printf("zip fileName = %s\n\n####\n contents of file %s\n###\n", entryName, builder);
} catch (Exception ex) {
ex.printStackTrace();
}
}
//use the entry to see if it's the file '1.txt'
//Read from the byte using file.getInputStream(entry)
}
}
}
/**
* The file was on the file system not a zip file,
* this is here for completeness for this example.
* otherwise.
*
* @param resource
* @param namespace
* @throws Exception
*/
private static void handleFile(URL resource, String namespace) throws Exception {
System.out.println("Handle this resource as a file " + resource);
URI uri = resource.toURI();
File file = new File(uri.getPath());
if (file.isDirectory()) {
for (File childFile : file.listFiles()) {
if (childFile.isDirectory()) {
continue;
}
String fileName = childFile.getName();
if (fileName.startsWith(namespace) && fileName.endsWith("txt")) {
try (FileReader reader = new FileReader(childFile)) {
StringBuilder builder = new StringBuilder();
int ch = 0;
while ((ch = reader.read()) != -1) {
builder.append((char) ch);
}
System.out.printf("fileName = %s\n\n####\n contents of file %s\n###\n", childFile, builder);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
} else {
String fileName = file.getName();
if (fileName.startsWith(namespace) && fileName.endsWith("txt")) {
try (FileReader reader = new FileReader(file)) {
StringBuilder builder = new StringBuilder();
int ch = 0;
while ((ch = reader.read()) != -1) {
builder.append((char) ch);
}
System.out.printf("fileName = %s\n\n####\n contents of file %s\n###\n", fileName, builder);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
回答by Emmanuel Angelo.R
This worked for me to copy an txt file from jar file to another txt file
这对我有用,可以将 txt 文件从 jar 文件复制到另一个 txt 文件
public static void copyTextMethod() throws Exception{
String inputPath = "path/to/.jar";
String outputPath = "Desktop/CopyText.txt";
File resStreamOut = new File(outputPath);
int readBytes;
JarFile file = new JarFile(inputPath);
FileWriter fw = new FileWriter(resStreamOut);
try{
Enumeration<JarEntry> entries = file.entries();
while (entries.hasMoreElements()){
JarEntry entry = entries.nextElement();
if (entry.getName().equals("readMe/tempReadme.txt")) {
System.out.println(entry +" : Entry");
InputStream is = file.getInputStream(entry);
BufferedWriter output = new BufferedWriter(fw);
while ((readBytes = is.read()) != -1) {
output.write((char) readBytes);
}
System.out.println(outputPath);
output.close();
}
}
} catch(Exception er){
er.printStackTrace();
}
}
}
回答by jk1971
private String loadResourceFileIntoString(String path) {
//path = "/resources/html/custom.css" for example
BufferedReader buffer = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(path)));
return buffer.lines().collect(Collectors.joining(System.getProperty("line.separator")));
}