【问题标题】:Listing the files in a directory of the current JAR file列出当前 JAR 文件目录中的文件
【发布时间】:2010-09-25 16:45:44
【问题描述】:

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

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

mtd/entity/creep/

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

最好的代码是什么?

【问题讨论】:

    标签: java class jar loading


    【解决方案1】:

    在提出问题 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);
            }
        }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这个答案有什么问题?我认为更大的问题是找到 jar 文件的路径——实际上提取内容应该很简单。
      【解决方案3】:

      请记住,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();
         }
      

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          旧的 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();
                  }
              }
          }
          

          【讨论】:

          • 在稍微弄乱了这个之后,我让它工作了。非常感谢!
          • 哦,这正是我现在需要的——谢谢!!
          猜你喜欢
          • 2012-08-11
          • 2013-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-28
          相关资源
          最近更新 更多