[英]Getting a directory inside a .jar
我正在嘗試訪問 jar 文件中的目錄。 我想通過目錄本身內的每個文件 go 。 例如,我嘗試使用以下內容:
URL imagesDirectoryURL=getClass().getClassLoader().getResource("Images");
if(imagesFolderURL!=null)
{
File imagesDirectory= new File(imagesDirectoryURL.getFile());
}
如果我測試這個小程序,它運行良好。 但是一旦我將內容放入jar,由於幾個原因,它不會。 如果我使用這段代碼,URL 總是指向 jar 之外,所以我必須把Images
目錄放在那里。 但是如果我使用new File(imagesDirectoryURL.toURI());
,它在 jar 內不起作用,因為我得到錯誤URI not hierarchical
。 我確信該目錄存在於 jar 中。 我應該如何獲取 jar 中的Images
內容?
Jars 中的路徑是路徑,而不是實際目錄,因為您可以在文件系統上使用它們。 要獲取 Jar 文件的特定路徑中的所有資源:
URL
。URL
獲取InputStream
。InputStream
構造一個ZipInputStream
。ZipEntry
,尋找與所需路徑的匹配項。
..當 Applet 不在 jar 內時,我還能測試它嗎? 還是我必須編寫兩種方法來獲取我的圖像?
ZipInputStream
不適用於文件系統目錄中的松散資源。 但是,我強烈建議使用諸如 Ant 之類的構建工具來構建(編譯/jar/簽名等)小程序。 編寫構建腳本並檢查它可能需要一個小時左右的時間,但此后您可以通過幾個按鍵和幾秒鍾的時間構建項目。
如果我想測試我的 Aplet,如果我總是必須提取並簽署我的 jar,那會很煩人
我不確定你的意思。 “提取物”從何而來? 如果我不清楚,沙盒小程序可以以這種方式從archive
屬性中提到的任何 Jar 加載資源。 您可能會做的另一件事是將資源 Jar 與小程序 Jar 分開。 資源通常比代碼更改更少,因此您的構建可能會采取一些捷徑。
我想我真的必須考慮將我的圖像放入 jar 之外的單獨目錄中。
如果您的意思是在服務器上,那么在沒有服務器幫助的情況下,將沒有實用的方法來獲取圖像文件的列表。 EG 一些服務器設置不安全,無法為任何沒有默認文件的目錄(例如 index.html)生成基於 HTML 的“文件列表”。
我只有一個 jar,我的課程、圖像和聲音都在其中。
好的 - 考慮將聲音和圖像移動到單獨的 Jar 中。 或者至少,將它們放入“無壓縮”的 Jar 中。 雖然 Zip 壓縮技術適用於類,但它們在壓縮(否則已經壓縮)媒體格式時效率較低。
我必須簽名,因為我使用“首選項”class 來保存用戶設置。”
小程序的Preferences
有替代方案,例如 cookies。 在插件 2 架構小程序的情況下,您可以使用Java Web 啟動小程序(仍然嵌入在瀏覽器中)。 JWS 提供 PersistenceService。 這是我的小演示。 的 PersistenceService 。
說到 JWS,這讓我想到:你絕對確定這款游戲作為一個小程序而不是一個使用 JWS 啟動的應用程序(例如使用JFrame
)會更好嗎?
Applet 會給您帶來無窮無盡的壓力,JWS 自從在 Java 1.2 中引入以來就提供了PersistenceService
。
這是一個解決方案,如果您使用 Java 7 ... “訣竅”是使用新文件 API,則該解決方案應該可以工作。 Oracle JDK 提供了一個FileSystem
實現,可用於查看/修改 ZIP 文件,包括 jar!
初步:抓取System.getProperty("java.class.path", ".")
,拆分為:
; 這將為您提供定義的類路徑中的所有條目。
首先,定義一個從類路徑條目中獲取FileSystem
的方法:
private static final Map<String, ?> ENV = Collections.emptyMap();
//
private static FileSystem getFileSystem(final String entryName)
throws IOException
{
final String uri = entryName.endsWith(".jar") || entryName.endsWith(".zip"))
? "jar:file:" + entryName : "file:" + entryName;
return FileSystems.newFileSystem(URI.create(uri), ENV);
}
然后創建一個方法來判斷文件系統中是否存在路徑:
private static boolean pathExists(final FileSystem fs, final String needle)
{
final Path path = fs.getPath(needle);
return Files.exists(path);
}
使用它來定位您的目錄。
一旦你有了正確的FileSystem
,使用它來遍歷你的目錄,使用.getPath()
和打開一個DirectoryStream
使用Files.newDirectoryStream()
。
完成后不要FileSystem
.close()
一個文件系統!
這是一個示例main()
,演示了如何讀取 jar 的所有根條目:
public static void main(final String... args)
throws IOException
{
final Map<String, ?> env = Collections.emptyMap();
final String jarName = "/opt/sunjdk/1.6/current/jre/lib/plugin.jar";
final URI uri = URI.create("jar:file:" + jarName);
final FileSystem fs = FileSystems.newFileSystem(uri, env);
final Path dir = fs.getPath("/");
for (Path entry : Files.newDirectoryStream(dir))
System.out.println(entry);
}
您可以使用 Spring 提供的PathMatchingResourcePatternResolver
。
public class SpringResourceLoader {
public static void main(String[] args) throws IOException {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// Ant-style path matching
Resource[] resources = resolver.getResources("/Images/**");
for (Resource resource : resources) {
System.out.println("resource = " + resource);
InputStream is = resource.getInputStream();
BufferedImage img = ImageIO.read(is);
System.out.println("img.getHeight() = " + img.getHeight());
System.out.println("img.getWidth() = " + img.getWidth());
}
}
}
我沒有對返回的Resource
做任何花哨的事情,但你明白了。
將此添加到您的 maven 依賴項(如果使用 maven):
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
這將直接在 Eclipse/NetBeans/IntelliJ和已部署的 jar 中工作。
從 IntelliJ 中運行給我以下 output:
resource = file [C:\Users\maba\Development\stackoverflow\Q12016222\target\classes\pictures\BMW-R1100S-2004-03.jpg]
img.getHeight() = 768
img.getWidth() = 1024
從命令行使用可執行文件 jar 運行給我以下 output:
C:\Users\maba\Development\stackoverflow\Q12016222\target>java -jar Q12016222-1.0-SNAPSHOT.jar
resource = class path resource [pictures/BMW-R1100S-2004-03.jpg]
img.getHeight() = 768
img.getWidth() = 1024
如果我了解您的問題,您想檢查 jar 中的目錄並檢查該目錄中的所有文件。您可以執行以下操作:
JarInputStream jar = new JarInputStream(new FileInputStream("D:\\x.jar"));
JarEntry jarEntry ;
while(true)
{
jarEntry = jar.getNextJarEntry();
if(jarEntry != null)
{
if(jarEntry.isDirectory() == false)
{
String str = jarEntry.getName();
if(str.startsWith("weblogic/xml/saaj"))
{
anything which comes here are inside weblogic\xml\saaj directory
}
}
}
}
您在此處查找的可能是 Jar 的 JarEntry 列表...我在研究生期間做過一些類似的工作...您可以在此處獲取修改后的 class ( Z80791B3AE7002CB88C246876D9FAAAA29DC40AB61DZ) -cs-research/source/browse/trunk/grad-ste-ufpe-brazil/ptf-add-on-dev/src/br/ufpe/cin/stp/global/filemanager/JarFileContentsLoader.java )請注意,ZE6B391A8D2C4D45902A23A8B68Z較舊的 Java class 不使用 Generics...
此 class 為給定令牌返回一組具有協議“jar:file:/”的 URL...
package com.collabnet.svnedge.discovery.client.browser.util;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class JarFileContentsLoader {
private JarFile jarFile;
public JarFileContentsLoader(String jarFilePath) throws IOException {
this.jarFile = new JarFile(jarFilePath);
}
/**
* @param existingPath an existing path string inside the jar.
* @return the set of URL's from inside the Jar (whose protocol is "jar:file:/"
*/
public Set<URL> getDirEntries(String existingPath) {
Set<URL> set = new HashSet<URL>();
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
String element = entries.nextElement().getName();
URL url = getClass().getClassLoader().getResource(element);
if (url.toString().contains("jar:file")
&& !element.contains(".class")
&& element.contains(existingPath)) {
set.add(url);
}
}
return set;
}
public static void main(String[] args) throws IOException {
JarFileContentsLoader jarFileContents = new JarFileContentsLoader(
"/u1/svnedge-discovery/client-browser/lib/jmdns.jar");
Set<URL> entries = jarFileContents.getDirEntries("impl");
Iterator<URL> a = entries.iterator();
while (a.hasNext()) {
URL element = a.next();
System.out.println(element);
}
}
}
output 將是:
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/constants/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/tasks/state/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/tasks/resolver/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/tasks/
可能以下代碼示例可以幫助您
Enumeration<URL> inputStream = BrowserFactory.class.getClassLoader().getResources(".");
System.out.println("INPUT STREAM ==> "+inputStream);
System.out.println(inputStream.hasMoreElements());
while (inputStream.hasMoreElements()) {
URL url = (URL) inputStream.nextElement();
System.out.println(url.getFile());
}
如果您真的想將 JAR 文件視為目錄,請查看TrueZIP 7 。 類似以下的內容可能是您想要的:
URL url = ... // whatever
URI uri = url.toURI();
TFile file = new TFile(uri); // File-look-alike in TrueZIP 7
if (file.isDirectory) // true for regular directories AND JARs if the module truezip-driver-file is on the class path
for (TFile entry : file.listFiles()) // iterate top level directory
System.out.println(entry.getPath()); // or whatever
問候, 克里斯蒂安
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.