【问题标题】:Iterate over folders in JAR file directly直接遍历 JAR 文件中的文件夹
【发布时间】:2013-06-29 14:01:57
【问题描述】:

我有以下code 来遍历类路径中的文件夹和文件并确定类并获取带有 ID 的字段并将它们打印到logger。如果我在我的 IDE 中运行此代码,这可以正常工作,但是如果我将我的项目打包到 JAR 文件中,并且将 JAR 文件打包到带有 launch4j 的 EXE 文件中,我将无法再次遍历我的类。 如果我尝试遍历 JAR/EXE 文件中的类,我会得到以下路径:

file:/C:/ENTWICKLUNG/java/workspaces/MyProject/MyProjectTest/MyProjectSNAPSHOT.exe!/com/abc/def

如何实现这一点来遍历我的 JAR/EXE 文件中的所有类?

public class ClassInfoAction extends AbstractAction
{
  /**
   * Revision/ID of this class from SVN/CVS.
   */
  public static String ID = "@(#) $Id ClassInfoAction.java 43506 2013-06-27 10:23:39Z $";

  private ClassLoader classLoader = ClassLoader.getSystemClassLoader();
  private ArrayList<String> classIds = new ArrayList<String>();
  private ArrayList<String> classes = new ArrayList<String>();
  private int countClasses = 0;

  @Override
  public void actionPerformed(ActionEvent e)
  {
    countClasses = 0;
    classIds = new ArrayList<String>();
    classes = new ArrayList<String>();

    getAllIds();

    Iterator<String> it = classIds.iterator();

    while (it.hasNext())
    {
      countClasses++;
      //here I print out the ID
    }
  }

  private void getAllIds()
  {
    String tempName;
    String tempAbsolutePath;

    try
    {
      ArrayList<File> fileList = new ArrayList<File>();
      Enumeration<URL> roots = ClassLoader.getSystemResources("com"); //it is a path like com/abc/def I won't do this path public
      while (roots.hasMoreElements())
      {
        URL temp = roots.nextElement();
        fileList.add(new File(temp.getPath()));
        GlobalVariables.LOGGING_logger.info(temp.getPath());
      }

      for (int i = 0; i < fileList.size(); i++)
      {
        for (File file : fileList.get(i).listFiles())
        {
          LinkedList<File> newFileList = null;
          if (file.isDirectory())
          {
            newFileList = (LinkedList<File>) FileUtils.listFiles(file, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);

            if (newFileList != null)
            {
              for (int j = 0; j < newFileList.size(); j++)
              {
                tempName = newFileList.get(j).getName();
                tempAbsolutePath = newFileList.get(j).getAbsolutePath();
                checkIDAndAdd(tempName, tempAbsolutePath);
              }
            }
          }
          else
          {
            tempName = file.getName();
            tempAbsolutePath = file.getAbsolutePath();
            checkIDAndAdd(tempName, tempAbsolutePath);
          }
        }
      }

      getIdsClasses();
    }
    catch (IOException e)
    {
    }
  }

  private void checkIDAndAdd(String name, String absolutePath)
  {
    if (name.endsWith(".class") && !name.matches(".*\\d.*") && !name.contains("$"))
    {
      String temp = absolutePath.replace("\\", ".");
      temp = temp.substring(temp.lastIndexOf(/* Class prefix */)); //here I put in the class prefix
      classes.add(FilenameUtils.removeExtension(temp));
    }
  }

  private void getIdsClasses()
  {
    for (int i = 0; i < classes.size(); i++)
    {
      String className = classes.get(i);

      Class<?> clazz = null;
      try
      {
        clazz = Class.forName(className);

        Field idField = clazz.getDeclaredField("ID");
        idField.setAccessible(true);

        classIds.add((String) idField.get(null));
      }
      catch (ClassNotFoundException e1)
      {
      }
      catch (NoSuchFieldException e)
      {
      }
      catch (SecurityException e)
      {
      }
      catch (IllegalArgumentException e)
      {
      }
      catch (IllegalAccessException e)
      {
      }

    }
  }
}

【问题讨论】:

  • 在运行这个 jar 之前,您需要在类路径中加载您导入的所需类。希望您没有错过它
  • 我不知道你到底是什么意思?我该怎么办?
  • 如果你使用 Java 7,就像Filesystems.newFileSystem("/path/to/the/jar") 一样简单。然后你可以使用所有的Filesystem/Path goodness。
  • 你能告诉我如何在我的程序中做到这一点吗?

标签: java file class reflection jar


【解决方案1】:

您不能从任意 URL 创建 File 对象并使用通常的文件系统遍历方法。现在,我不确定 launch4j 是否有什么不同,但至于迭代纯 JAR 文件的内容,您可以使用官方 API:

JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile file = connection.getJarFile();
Enumeration<JarEntry> entries = file.entries();
while (entries.hasMoreElements()) {
    JarEntry e = entries.nextElement();
    if (e.getName().startsWith("com")) {
        // ...
    }
}

sn-p 上面列出了url 引用的JAR 文件中的所有条目,即文件和目录。

【讨论】:

    猜你喜欢
    • 2012-12-07
    • 2017-04-03
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2023-01-20
    • 2014-09-28
    • 2019-05-08
    相关资源
    最近更新 更多