列出当前JAR文件目录中的文件

15

我正在使用JAVA制作游戏,我想列出我的jar包中某个目录下的文件清单,以便确保在游戏中使用这些类时有一个列表。

例如,假设在我的jar包中有一个目录:

mtd/entity/creep/

我想使用另一个在jar包里的Java类的代码,获取那个目录下所有.class文件的列表。

最好的代码是什么?

5个回答

7

虽然下面的代码是旧的Java1.4版本,但您可以了解其思路:

private static List getClassesFromJARFile(String jar, String packageName) throws Error
{
    final List classes = new ArrayList();
    JarInputStream jarFile = null;
    try
    {
        jarFile = new JarInputStream(new FileInputStream(jar));
        JarEntry jarEntry;
        do 
        {       
            try
            {
                jarEntry = jarFile.getNextJarEntry();
            }
            catch(IOException ioe)
            {
                throw new CCException.Error("Unable to get next jar entry from jar file '"+jar+"'", ioe);
            }
            if (jarEntry != null) 
            {
                extractClassFromJar(jar, packageName, classes, jarEntry);
            }
        } while (jarEntry != null);
        closeJarFile(jarFile);
    }
    catch(IOException ioe)
    {
        throw new CCException.Error("Unable to get Jar input stream from '"+jar+"'", ioe);
    }
    finally
    {
        closeJarFile(jarFile);
    }
   return classes;
}
private static void extractClassFromJar(final String jar, final String packageName, final List classes, JarEntry jarEntry) throws Error
{
    String className = jarEntry.getName();
    if (className.endsWith(".class")) 
    {
        className = className.substring(0, className.length() - ".class".length());
        if (className.startsWith(packageName))
        {
            try
            {
                classes.add(Class.forName(className.replace('/', '.')));
            } catch (ClassNotFoundException cnfe)
            {
                throw new CCException.Error("unable to find class named " + className.replace('/', '.') + "' within jar '" + jar + "'", cnfe);
            }
        }
    }
}
private static void closeJarFile(final JarInputStream jarFile)
{
    if(jarFile != null) 
    { 
        try
        {
            jarFile.close(); 
        }
        catch(IOException ioe)
        {
            mockAction();
        }
    }
}

经过一点儿折腾,我终于让它工作了。非常感谢! - James Van Boxtel
哦,这恰好是我现在需要的 - 谢谢! - user21037

3

最好的方法可能是在编译时列出类。

还有一种脆弱的运行时方法。获取Class (this.getClass()MyClass.class)。调用getProtectionDomain。调用getCodeSource。调用getLocation。调用openConnection。(或者打开一个资源。)强制转换为JarURLConnection。调用getJarFile。调用entries。迭代检查getName。我真的不建议使用这种方法。


2

在这个问题提出10年后,我提出了另一种完成工作的方法:

"Original Answer"翻译成中文是"最初的回答"。

private static void listFilesFromDirectoryInsideAJar(String pathToJar,String directory,String extension) {
        try {
            JarFile jarFile = new JarFile(pathToJar);
            Enumeration<JarEntry> e = jarFile.entries();
            while (e.hasMoreElements()) {
                JarEntry candidat = e.nextElement();
                if (candidat.getName().startsWith(directory) && 
                    candidat.getName().endsWith(extension))
                    LOG.info(candidat.getName());
            }
        } catch (IOException e) {
            LOG.error(e.getMessage(),e);
        }
    }

0

这是不可能的,因为Java没有直接访问加载类的jar文件的功能。您可以尝试解析java.class.path系统属性以查找它,但在所有情况下都无法使用此方法。或者您可以限制jar文件必须驻留的位置,或以另一种方式提供类列表(例如通过清单文件)。


这个答案有什么问题吗?我认为更大的问题在于找到jar文件的路径 - 实际上提取内容应该相当简单。 - Ilja Preuß

0

请记住,JAR文件只是重命名的ZIP文件,而且在Java中读取ZIP文件的内容非常容易:

    File jarName = null;
    try
    {
        jarName = new File (Dir.class.getProtectionDomain().getCodeSource().getLocation().toURI());
    }
    catch (Exception e)
    {
        e.printStackTrace();    
    }

    try 
    {
      ZipFile zf=new ZipFile(jarName.getAbsoluteFile());
      Enumeration e=zf.entries();
      while (e.hasMoreElements()) 
      {
          ZipEntry ze=(ZipEntry)e.nextElement();
          System.out.println(ze.getName());
      }
      zf.close();
   } catch (IOException e) 
   {
      e.printStackTrace();
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接