列出jar中指定包下的所有文件

感谢:http://blog.csdn.net/baibinboss/article/details/68947929
终于找到完美方法!!!

列出jar中指定包下的所有文件

环境

首先是jar中的文件,而不是开发环境中的文件(开发环境中的文件,eclipse中是bin目录下)。这两种情况下读文件的方式完全不同

代码

注意:如果没有打包(如在开发环境中),第8行代码protocol为file

String packagePath="com.ccc";
try {
    Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packagePath.replace(".", "/"));
    while (dirs.hasMoreElements()) {
        URL url=dirs.nextElement();
        String protocol = url.getProtocol();
        //如果该在jar中protocol为jar,如果没有打包(如在开发环境中)为file
        if("jar".equals(protocol)){
            //转换为JarURLConnection
            JarURLConnection connection = (JarURLConnection) url.openConnection();
            if(connection!=null){
                // 找到包含该包路径的 jar 包
                JarFile jarFile = connection.getJarFile();
                if (jarFile != null) {
                    //得到该jar文件下面的类实体
                    Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
                    // 遍历该 jar 包下的所有文件、子包
                    while (jarEntryEnumeration.hasMoreElements()) {
                        /*entry的结果大概是这样:
                                org/
                                org/junit/
                                org/junit/rules/
                                org/junit/runners/
                                org/junit/rules/Main.class
                                org/junit/rules/Test.class
                        */
                        JarEntry entry = jarEntryEnumeration.nextElement();
                        String path = entry.getName();
                        // 将路径中的 / 替换成 .
                        String classPath = path.replaceAll("/", ".");
                        /*
                         获取的是 当前 jar下的所有文件、路径,所以这里要过滤
                         只处理 前缀是指定 包路径的 class文件
                         */
                        if (classPath.startsWith(packagePath) && !entry.isDirectory() ) {

                            if (classPath.endsWith(".class")) {
                                // 截取类名,不包含 .class
                                String classAllPath = classPath.substring(0, classPath.lastIndexOf("."));
                                //Class<?> clazz = Class.forName(classAllPath);
                                System.out.println(classAllPath)
                            }

                        }
                    }
                }
            }
        }

    }
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

代码分析

多个jar包

工程中可能有多个jar都包含指定包,比如:a.jar,b.jar,c.jar中都包含 com.my.utils 包,也就是说需要从多个jar中寻找指定包。

所以要用下面代码:

Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packagePath.replace(".", "/"));

查找jar包

找到包含该包路径的 jar 包

JarFile jarFile = connection.getJarFile();

获取包路径

找到jar包后,再遍历,过滤出指定包路径的 .class 文件