14

我正在用 JAVA 制作一个游戏,我想在我的 jar 中的某个目录中提供一个文件列表,这样我就可以确保有一个要在游戏中使用的类的列表。

例如说在我​​的罐子里我有一个目录

mtd/entity/creep/

我想使用 jar 中另一个类的 java 代码获取该目录中所有 .class 文件的列表。

这样做的最佳代码是什么?

4

5 回答 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();
        }
    }
}
于 2008-12-06T21:56:04.293 回答
2

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

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);
        }
    }
于 2019-07-26T13:03:43.307 回答
1

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

有一种脆弱的运行时方法。带你ClassMyClass.classthis.getClass())。打电话getProtectionDomain。打电话getCodeSource。打电话getLocation。打电话openConnection。(或者打开一个资源。)投射到JarURLConnection. 打电话getJarFile。打电话entries。遍历检查getName。我真的不推荐这种方法。

于 2008-12-07T00:22:57.477 回答
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();
   }
于 2008-12-07T00:23:49.737 回答
-1

这是不可能的,因为 Java 不提供对从中加载类的 jar 文件的直接访问。您可以尝试解析 java.class.path 系统属性以找到它,但这并非在所有情况下都有效。或者您可以限制 jar 文件必须驻留的位置,或者以不同的方式提供类列表(例如通过清单文件)。

于 2008-12-06T21:59:08.093 回答