简体   繁体   English

将文件列在当前JAR文件的目录中

[英]Listing the files in a directory of the current JAR file

I am making a game in JAVA where I want to come up with a list of files in a certain directory in my jar so I can make sure to have a list of those classes to be used in the game. 我正在JAVA制作游戏,我想在我的jar中的某个目录中找到一个文件列表,这样我就可以确保在游戏中使用这些类的列表。

For example say in my jar I have a directory 例如,在我的jar中我有一个目录

mtd/entity/creep/

I want to get a list of all the .class files in that directory using java code from another class in the jar . 我想使用jar中另一个类的java代码获取该目录中所有.class文件的列表。

What is the best code to do so? 这样做的最佳代码是什么?

Old java1.4 code, but that would give you the idea: 旧的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();
        }
    }
}

Probably the best approach is to list the classes at compile time. 可能最好的方法是在编译时列出类。

There is a fragile runtime approach. 有一种脆弱的运行时方法。 Take you Class ( MyClass.class of this.getClass() ). 拿你的Classthis.getClass() MyClass.class )。 Call getProtectionDomain . 调用getProtectionDomain Call getCodeSource . 调用getCodeSource Call getLocation . 调用getLocation Call openConnection . 调用openConnection (Alternatively open a resource.) Cast to JarURLConnection . (或者打开一个资源。)转换为JarURLConnection Call getJarFile . 调用getJarFile Call entries . 来电entries Iterate through checking getName . 通过检查getName迭代。 I really do not recommend this approach. 我真的不推荐这种方法。

10 years after the question, I propose an another way to do the job: 问题发生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);
        }
    }

Remember that JAR files are just ZIP files renamed, and it's very easy to read the contents of ZIP files in Java: 请记住, 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();
   }

It's not possible, as Java doesn't provide direct access to the jar file the classes are loaded from. 这是不可能的,因为Java不提供对从中加载类的jar文件的直接访问。 You could try to parse the java.class.path system property to find it, but that wouldn't work under all circumstances. 您可以尝试解析java.class.path系统属性以找到它,但这在所有情况下都不起作用。 Or you could restrict on where the jar file has to reside, or provide the list of the classes in a different way (for example via the manifest file). 或者您可以限制jar文件必须驻留的位置,或者以不同的方式提供类的列表(例如,通过清单文件)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM