Java:IO/NIO篇,利用IO遍历目录示范(示范:从指定目录的JAR包中查找指定类)

1. 问题

因为项目有时需要查找一个类属于哪个JAR包,知道类名,知道大概路径,但不知道具体在哪个JAR包中,所以写了这样的一个小程序,来实现查找JAR包的作用。

2. 解决

package com.clzhang.sample.io;

import java.util.*;
import java.io.*;
import java.util.jar.*;

/**
 * 这是一个从指定目录(包括子目录)的各种JAR/ZIP包中查找指定类文件的程序。
 * 指定目录形如:C:\JavaApp\android-sdk-windows\platforms\android-17
 * 指定目录也可以直接是一个JAR/ZIP包,比如:
 * C:\JavaApp\android-sdk-windows\platforms\android-17\data\layoutlib.jar
 * 
 * 指定类形如:libcore.net.UriCodec
 * 
 * 示范:可以从C:\JavaApp\android-sdk-windows\platforms\android-17\data目录中的layoutlib.jar包中找到:libcore.net.UriCodec类
 * 也可以从C:\JavaApp\android-sdk-windows\platforms目录的子目录中找到:libcore.net.UriCodec类,需要时间稍长些而已。
 * 
 * @author acer
 * 
 */
public class FindClassInJar {
    // 查找目录起始位置
    private String m_libDir;

    // 需要查找的类名
    private String m_classname;

    // 总计查找到的个数
    int m_count = 0;

    // 构造器 libDir  查找目录起始位置 classname 需要查找的类名
    public FindClassInJar(String libDir, String classname) {
        m_libDir = libDir;
        m_classname = classname;
    }

    // 文件过滤器,仅目录、JAR/ZIP文件格式通过
    class JarZipFileFilter implements FileFilter {
        public boolean accept(File file) {
            if (file.isDirectory())
                return true;

            String name = file.getName().toLowerCase();
            if (name.endsWith(".jar") || name.endsWith(".zip")) {
                return true;
            } else {
                return false;
            }
        }
    }

    // 开始处理,与真实处理的分开了,主要原因是调用格式可能是从目录开始查找,也可能是从文件开始查找,
    // 所以让外界直接调用checkDirectory()方法似乎有些不太合适。
    public void process() throws Exception {
        checkDirectory(m_libDir);
    }

    // 检查目录/文件,命名似乎有些不太合适,先这样吧。
    private void checkDirectory(String libDir) throws Exception {
        File file = new File(libDir);
        if (file.isFile()) {
            // 允许不是目录,直接是一个文件(JAR、ZIP等)
            if (checkFile(file)) {
                m_count++;
                System.out.println(file.getName() + "包中包含了类:" + m_classname);
            }
        } else {
            File[] files = file.listFiles(new JarZipFileFilter());

            for (int i = 0; i < files.length; i++) {
                File f = files[i];
                if (f.isDirectory()) {
                    checkDirectory(f.getAbsolutePath());
                } else {
                    System.out.println("正在检查:" + f.getAbsolutePath());

                    if (checkFile(f)) {
                        m_count++;
                        System.out.println(f.getName() + "包中包含了类:"
                                + m_classname);
                    }
                }
            }
        }
    }

    // 从JAR/ZIP包中查找类文件
    private boolean checkFile(File f) {
        boolean result = false;

        try {
            JarFile jarFile = new JarFile(f);
            Enumeration<JarEntry> enu = jarFile.entries();
            while (enu.hasMoreElements()) {
                JarEntry entry = enu.nextElement();
                String name = entry.getName();
                if (entry.isDirectory()) {
                    continue;
                }

                if (name.equals(m_classname)) {
                    result = true;

                    break;
                }
            }
            jarFile.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return result;
    }

    // 取得总计查找到的目标类数量
    private int getCount() {
        return m_count;
    }

    public static void main(String args[]) throws Exception {
        String libDir = "D:\\Resources";
        // String libDir = "C:\\JavaApp\\android-sdk-windows\\platforms\\android-17\\data\\layoutlib.jar";
        String classname = "org.slf4j.impl.StaticLoggerBinder";
        
        classname = classname.replaceAll("\\.", "/") + ".class";
        
        System.out.println("开始在路径:" + libDir + "中查找:" + classname + "类......");
        FindClassInJar ins = new FindClassInJar(libDir, classname);
        ins.checkDirectory(libDir);
        System.out.println("总计找到:" + ins.getCount() + "个符合要求的类!");
    }
}
原文地址:https://www.cnblogs.com/nayitian/p/2866719.html