简单的文件操作工具类(File)

1.解决问题

通过形如:com.xxx.yyy.zzz形式的包名,加载包下所有的类

2.代码:

package com.chuyutech.rssp.openservice.service.data;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @description: 简单的文件操作类,包含一些文件的基本操作
 * 
 * @author cwh
 *
 */
public class FileOpreation {

	/**
	 * 根据包名访问磁盘文件
	 * 
	 * @param packageName:形如com.xxx.yyy.zzz以点号分割
	 */
	public static Set<Class<?>> getClazz(String packageName) {
		// 是否递归
		boolean isRecursion = true;
		// 定义变量,保存class文件
		Set<Class<?>> clazz = new LinkedHashSet<Class<?>>();
		char dot = '.';
		char sprit = '/';
		try {
			// 根据当前线程获取ContextClassLoader类加载器 需注意:分隔符的转换
			// getResources方法定义的资源是 '/' 分隔符

			Enumeration<URL> resources = Thread.currentThread().getContextClassLoader()
					.getResources(packageName.replace(dot, sprit));
			// 遍历枚举
			while (resources.hasMoreElements()) {
				URL url = resources.nextElement();
// url:file:/E:/03.WorkSpaceToNew/soldier-openservice/target/classes/com/chuyutech/rssp/openservice/common/db/dao
				System.out.println("url:" + url.toString());
				// 获取协议名称
				String protocol = url.getProtocol();
				// 如果为文件类型 接下来就是File类的操作
				if (protocol.equals("file")) {
					//					使用特定的编码方案解码url
					String packagePath = URLDecoder.decode(url.getFile(), "UTF-8");
//					调用方法递归获取文件
					getClazzFromPath(packageName, packagePath, isRecursion, clazz);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return clazz;
	}

	/**
	 * 获取文件中class文件
	 * 
	 * @param packageName:包名;
	 *            packagePath:文件路径;isRecursion:是否递归
	 */
	public static void getClazzFromPath(String packageName, String packagePath, boolean isRecursion,
			Set<Class<?>> clazz) {
		char dot = '.';
		// 根据路径名获取File文件对象
		File file = new File(packagePath);

		if (!file.exists() || !file.isDirectory()) {
			return;
		}
		// 以File数组的形式列出所有的文件
		File[] files = file.listFiles(new FileFilter() {
			// 匿名内部类重写FIleFilter
			@Override
			public boolean accept(File pathName) {
	// 自定义过滤规则 如果可以循环(包含子目录) 或者是以.class结尾的文件(编译好的java类文件)
				return ((isRecursion && pathName.isDirectory()) || pathName.getName().endsWith(".class"));
			}
		});
		// 遍历files
		for (File destFile : files) {
			// 如果是目录 则继续扫描
			if (destFile.isDirectory()) {
				getClazzFromPath(packageName + dot + destFile.getName(), destFile.getAbsolutePath(), isRecursion,
						clazz);
			} else {
				// 如果是编译后java类文件 去掉后面的.class 只留下类名
				String fileName = destFile.getName().substring(0, destFile.getName().lastIndexOf(dot));
				// 添加到集合中去 通过完整包名+"."+文件名 加载class
				try {
					// Class<?> forName = Class.forName(packageName + dot +
					// className); 此方法在会初始化所加载类的static静态代码块
					Class<?> loadClass = Thread.currentThread().getContextClassLoader()
							.loadClass(packageName + dot + fileName);
					clazz.add(loadClass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}

		}
	}

	public static void main(String[] args) {
		String packageName = "com.chuyutech.rssp.openservice.common.db.dao";
		Set<Class<?>> clazz = getClazz(packageName);
		System.out.println(clazz.size());
		for (Class<?> class1 : clazz) {
			System.out.println(class1.getName());
		}
	}

}

3.总结:

        3.1:实现的大致逻辑:

            根据当前线程获取ContextClassLoader类加载器 ,通过类加载器的getResources(String name)方法获取包名所对应的URL.

            通过URL获取绝对路径,使用File类的 java.io.listFiles(FileFilter filter)列出所有的文件或目录

            对上一步获取的文件或目录递归调用,最后通过Thread.currentThread().getContextClassLoader()
                            .loadClass(className)获取到Class对象保存到set集合中.

           3.2:注意:分隔符的转换:getResources方法定义的资源是 '/' 分隔符


4.结果打印:

---------------------over-----------------------

猜你喜欢

转载自my.oschina.net/u/3406827/blog/1789318