下面是我在另一條評論中承諾的代碼......這不是我記得的,但它可能會讓你開始。
本質上你調用:String fileName = FileUtils.getFileName(Main.class,「foo.txt」);
它會發現該文件在磁盤或JAR文件中。如果它在JAR文件中,則將其提取到臨時目錄。然後,您可以使用「新文件(文件名)」來打開該文件,無論以前它在哪裏,都將在磁盤上。
我會做的是看看getFile方法,看看你可以用JAR文件做什麼來迭代它的內容,並找到給定目錄中的文件。
就像我說的,不完全是你想要的,但確實爲你做了很多最初的工作。
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class FileUtils
{
public static String getFileName(final Class<?> owner,
final String name)
throws URISyntaxException,
ZipException,
IOException
{
String fileName;
final URI uri;
try
{
final String external;
final String decoded;
final int pos;
uri = getResourceAsURI(owner.getPackage().getName().replaceAll("\\.", "/") + "/" + name, owner);
external = uri.toURL().toExternalForm();
decoded = external; // URLDecoder.decode(external, "UTF-8");
pos = decoded.indexOf(":/");
fileName = decoded.substring(pos + 1);
}
catch(final FileNotFoundException ex)
{
fileName = null;
}
if(fileName == null || !(new File(fileName).exists()))
{
fileName = getFileNameX(owner, name);
}
return (fileName);
}
private static String getFileNameX(final Class<?> clazz, final String name)
throws UnsupportedEncodingException
{
final URL url;
final String fileName;
url = clazz.getResource(name);
if(url == null)
{
fileName = name;
}
else
{
final String decoded;
final int pos;
decoded = URLDecoder.decode(url.toExternalForm(), "UTF-8");
pos = decoded.indexOf(":/");
fileName = decoded.substring(pos + 1);
}
return (fileName);
}
private static URI getResourceAsURI(final String resourceName,
final Class<?> clazz)
throws URISyntaxException,
ZipException,
IOException
{
final URI uri;
final URI resourceURI;
uri = getJarURI(clazz);
resourceURI = getFile(uri, resourceName);
return (resourceURI);
}
private static URI getJarURI(final Class<?> clazz)
throws URISyntaxException
{
final ProtectionDomain domain;
final CodeSource source;
final URL url;
final URI uri;
domain = clazz.getProtectionDomain();
source = domain.getCodeSource();
url = source.getLocation();
uri = url.toURI();
return (uri);
}
private static URI getFile(final URI where,
final String fileName)
throws ZipException,
IOException
{
final File location;
final URI fileURI;
location = new File(where);
// not in a JAR, just return the path on disk
if(location.isDirectory())
{
fileURI = URI.create(where.toString() + fileName);
}
else
{
final ZipFile zipFile;
zipFile = new ZipFile(location);
try
{
fileURI = extract(zipFile, fileName);
}
finally
{
zipFile.close();
}
}
return (fileURI);
}
private static URI extract(final ZipFile zipFile,
final String fileName)
throws IOException
{
final File tempFile;
final ZipEntry entry;
final InputStream zipStream;
OutputStream fileStream;
tempFile = File.createTempFile(fileName.replace("/", ""), Long.toString(System.currentTimeMillis()));
tempFile.deleteOnExit();
entry = zipFile.getEntry(fileName);
if(entry == null)
{
throw new FileNotFoundException("cannot find file: " + fileName + " in archive: " + zipFile.getName());
}
zipStream = zipFile.getInputStream(entry);
fileStream = null;
try
{
final byte[] buf;
int i;
fileStream = new FileOutputStream(tempFile);
buf = new byte[1024];
i = 0;
while((i = zipStream.read(buf)) != -1)
{
fileStream.write(buf, 0, i);
}
}
finally
{
close(zipStream);
close(fileStream);
}
return (tempFile.toURI());
}
private static void close(final Closeable stream)
{
if(stream != null)
{
try
{
stream.close();
}
catch(final IOException ex)
{
ex.printStackTrace();
}
}
}
}
編輯:
對不起,我沒有時間來對這一權利的工作,現在(如果我得到一些我會做到這一點並張貼在這裏的代碼)。這就是我會做,雖然:
- 看那ZipFile類,並使用entries()方法來發現所有的文件/目錄中的zip文件。
- ZipEntry有一個isDirectory()方法,您可以使用它來弄清楚它是什麼。
- 我認爲我發佈在this answer中的代碼將爲您提供一種方法來選擇一個臨時目錄來提取內容。
- 我認爲我發佈在this answer的代碼可以幫助將ZipEntry內容複製到文件系統。
- 一旦這些項目在文件系統上,您已經擁有的用於迭代目錄的代碼仍然可以工作。您可以在上面的代碼中爲FileUtils類添加一個新方法,並能夠像現在這樣查找所有文件。
有可能是一個更好的方法來做到這一點,但我的頭頂我認爲這將工作。
如何使用ant build腳本將所有類和資源文件添加到自我可執行Jar文件中? – Pool 2010-03-07 00:10:33
聽起來不錯,但我不知道螞蟻不幸的是:(爲什麼有人downvote這個? – Martin 2010-03-07 01:49:28
如承諾我已經發布了一些代碼作爲一個新的答案。它可能會幫助你開始尋找在JAR內的每個目錄中的文件 – TofuBeer 2010-03-07 17:36:52