【问题标题】:How do I access the content of folders inside a jar file?如何访问 jar 文件中的文件夹内容?
【发布时间】:2011-06-30 23:58:53
【问题描述】:

我需要查看特定包中的文件名。目前,我正在执行以下操作:

ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL packageUrl = loader.getResource(getPackage().replace('.', '/'));
File packageDir = new File(packageUrl.getFile());

// Work with the files inside the directory

这实际上在 Eclipse 中工作得很好,因为默认情况下它不会打包我的应用程序。然而,当我从一个 jar 文件运行它时,我在 packageUrl 上得到一个 NullPointerException

那么,如何获取 jar 中的包的内容列表?我的研究建议使用getResourceAsStream,但我不太确定如何使用InputStream 探索目录,如果可能的话。

【问题讨论】:

    标签: java jar classloader


    【解决方案1】:

    您可以获取 jar 文件的路径并使用 ZipInputStream 将其打开,列出该 jar 中的所有文件。

    要知道运行jar的路径,尝试使用:

    InputStream in = MyClass
                    .class
                    .getProtectionDomain()
                    .getCodeSource()
                    .getLocation()
                    .openStream();
    

    另请参阅:How do I list the files inside a JAR file?

    更新

    我已经编译并运行了您的解决方案并且运行良好:

    C:\java\injar>dir
     El volumen de la unidad C no tiene etiqueta.
     El número de serie del volumen es: 22A8-203B
    
     Directorio de C:\java\injar
    
    21/02/2011  06:23 p.m.    <DIR>          .
    21/02/2011  06:23 p.m.    <DIR>          ..
    21/02/2011  06:23 p.m.             1,752 i18n.jar
    21/02/2011  06:23 p.m.    <DIR>          src
    21/02/2011  06:21 p.m.    <DIR>          x
    
    C:\java\injar>jar -tf i18n.jar
    META-INF/
    META-INF/MANIFEST.MF
    I18n.class
    x/
    x/y/
    x/y/z/
    x/y/z/hola.txt
    
    C:\java\injar>type src\I18n.java
    import java.util.*;
    import java.net.*;
    import java.util.jar.*;
    class I18n {
        public static void main( String ... args ) {
            getLocaleListFromJar();
        }
        private static List<Locale> getLocaleListFromJar() {
            List<Locale> locales = new ArrayList<Locale>();
            try {
                URL packageUrl = I18n.class.getProtectionDomain().getCodeSource().getLocation();
                JarInputStream jar = new JarInputStream(packageUrl.openStream());
                while (true) {
                    JarEntry entry = jar.getNextJarEntry();
                    if (entry == null) {
                        System.out.println( "entry was null ");
                        break;
                    }
                    String name = entry.getName();
                    System.out.println( "found : " +name );
                    /*if (resourceBundlePattern.matcher(name).matches()) {
                        addLocaleFromResourceBundle(name, locales);
                    }*/
               }
            } catch (Exception e) {
                System.err.println(e);
                return null;
                //return getLocaleListFromFile(); // File based implementation in case resources are not in jar
            }
            return locales;
        }
    }
    
    
    C:\java\injar>java -jar i18n.jar
    found : I18n.class
    found : x/
    found : x/y/
    found : x/y/z/
    found : x/y/z/hola.txt
    entry was null
    

    【讨论】:

    • 我试过了,但getNextEntry() 似乎总是返回nullgetLocation() 返回rsrc:./。关于可能是什么问题的任何想法?顺便说一句,我正在尝试从我的应用程序自己的 jar 中读取文件......我想我应该提到这一点。
    • 你有一些我们可以看到的样本吗?我已经使用前面提到的代码来加载我的 jar 中的所有图像并且运行良好:meta.stackexchange.com/questions/20420/…
    • 看着它。与此同时,你注意到了吗? stackoverflow.com/questions/1429172/list-files-inside-a-jar/…
    • 是的。我的实施基于该答案,但做法不同。我错过了什么吗?
    • 这很奇怪。你打电话给getLocation() 会得到什么回报?该方法是否返回相对于调用类的位置?我正在寻找的条目位于不同的包树上,所以这可能是问题所在。
    【解决方案2】:

    您可以使用JarInputStream 来读取jar 文件的内容。您将遍历getNextJarEntry() 返回的JarEntry 对象,这些对象具有getName()。如果您不关心任何特定于 jar 的元数据,例如代码签名者或其他 Manifest 条目,您可以坚持使用 ZipInputStream 超类。

    【讨论】:

    • +1 用于Jar-specific 类,我将来可能需要它。
    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 2023-04-10
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    相关资源
    最近更新 更多