簡體   English   中英

在 a.jar 中獲取目錄

[英]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 文件的特定路徑中的所有資源:

  • 獲得指向 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

我認為您可以直接訪問 ZIP/JAR 文件中的資源請參閱教程它為您的問題提供解決方案

如何從 JAR 和 zip 檔案中提取 Java 資源

希望有幫助

如果我了解您的問題,您想檢查 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM