java查找反复类/jar包/普通文件

开发web应用时,有时更新了类却没有生效,事实上是由于jboss/tomcat中其它公布包下有同名类(包含全路径都同样)。

于是萌发了做个程序来检查指定文件夹是否存在反复类(通过asm从类文件里取类的全路径),扩展开来,还支持查找反复的文件(按文件md5进行比較),反复的jar文件。

主要代码例如以下:

package cn.jerryhouse.util.dup_files;

import java.io.File;

public abstract class FileProcessor {
	private long totalFileCount = 0;
	private long processedFileCount = 0;
	public void processFiles(File[] dirs) throws Exception {
		for (File file : dirs) {
			processFile(file);
		}
	}

	public void processFile(File file) throws Exception {
		if (file.isFile()) {
			if (isFileAccepted(file)) {
				handleFile(file);
				processedFileCount++;
			}
			totalFileCount++;
		} else {
			File[] files = file.listFiles();
			for (File fileInDir : files) {
				processFile(fileInDir);
			}
		}
	}

	protected boolean isFileAccepted(File file) throws Exception {
		return true;
	}

	protected abstract void handleFile(File file);

	public long getTotalFileCount() {
		return totalFileCount;
	}

	public long getProcessedFileCount() {
		return processedFileCount;
	}
}

package cn.jerryhouse.util.dup_files;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class FileDupFinder extends FileProcessor {
	protected Map<String, List<String>> fileMap = new ConcurrentHashMap<String, List<String>>();
	public void analyseResult() {
		boolean foundDup = false;
		for (Entry<String, List<String>> entry : fileMap.entrySet()) {
			List<String> classPathList = entry.getValue();
			if (classPathList.size() > 1) {
				System.out.println(" paths:"
						+ classPathList);
				foundDup = true;
			}
		}
		if (foundDup == false) {
			System.out.println("No duplicate file found.");
		}
	}

	protected void handleFile(final File file) {
		try {
			String fileMD5 = FileDigest.getFileMD5(file);
			try {
				List<String> list;
				if (fileMap.get(fileMD5) != null) {
					list = fileMap.get(fileMD5);
					list.add(file.getCanonicalPath());
				} else {
					list = new LinkedList<String>();
					list.add(file.getCanonicalPath());
					fileMap.put(fileMD5, list);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
package cn.jerryhouse.util.dup_files;

import java.io.File;

public class JarFileDupFinder extends FileDupFinder {

	protected boolean isFileAccepted(final File file) throws Exception
	{
		if(file.getCanonicalPath().endsWith(".jar"))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

}
package cn.jerryhouse.util.dup_files;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

public class ClassDupFinder extends FileDupFinder {

	protected boolean isFileAccepted(final File file) throws Exception {
		if (file.getCanonicalPath().endsWith(".class")) {
			return true;
		} else {
			return false;
		}
	}

	public void analyseResult() {
		boolean foundDup = false;
		for (Entry<String, List<String>> entry : fileMap.entrySet()) {
			List<String> classPathList = entry.getValue();
			if (classPathList.size() > 1) {
				System.out.println("class:" + entry.getKey() + " paths:"
						+ classPathList);
				foundDup = true;
			}
		}
		if (foundDup == false) {
			System.out.println("No duplicate class found.");
		}
	}

	protected void handleFile(final File file) {
		try {
			String filePath = file.getCanonicalPath();
			ClassVisitor visitor = new ClassVisitor() {
				@Override
				public void visit(int version, int access, String name,
						String signature, String superName, String[] interfaces) {
					try {
						List<String> list;
						if (fileMap.get(name) != null) {
							list = fileMap.get(name);
							list.add(file.getCanonicalPath());
						} else {
							list = new LinkedList<String>();
							list.add(file.getCanonicalPath());
							fileMap.put(name, list);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				@Override
				public void visitSource(String source, String debug) {
				}

				@Override
				public void visitOuterClass(String owner, String name,
						String desc) {
				}

				@Override
				public AnnotationVisitor visitAnnotation(String desc,
						boolean visiable) {
					return null;
				}

				@Override
				public void visitAttribute(Attribute attr) {
				}

				@Override
				public void visitInnerClass(String name, String outerName,
						String innerName, int access) {
				}

				@Override
				public FieldVisitor visitField(int access, String name,
						String desc, String signature, Object value) {
					return null;
				}

				@Override
				public MethodVisitor visitMethod(int access, String name,
						String desc, String signature, String[] exceptions) {
					return null;
				}

				@Override
				public void visitEnd() {
				}
			};
			ClassReader cr = new ClassReader(new FileInputStream(filePath));
			cr.accept(visitor, 0);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
package cn.jerryhouse.util.dup_files;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

public class FileDigest {
	/**
	 * 获取单个文件的MD5值
	 * @param file
	 */
	public static String getFileMD5(File file) {
		if (!file.isFile()) {
			return null;
		}
		MessageDigest digest = null;
		FileInputStream in = null;
		byte buffer[] = new byte[1024];
		int len;
		try {
			digest = MessageDigest.getInstance("MD5");
			in = new FileInputStream(file);
			while ((len = in.read(buffer, 0, 1024)) != -1) {
				digest.update(buffer, 0, len);
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		BigInteger bigInt = new BigInteger(1, digest.digest());
		return bigInt.toString(16);
	}

	/**
	 * 获取文件夹中文件的MD5值
	 * @param file
	 * @param listChild 为true时,递归子文件夹中的文件;否则不递归
	 */
	public static Map<String, String> getDirMD5(File file, boolean listChild) {
		if (!file.isDirectory()) {
			return null;
		}
		Map<String, String> map = new HashMap<String, String>();
		String md5;
		File files[] = file.listFiles();
		for (int i = 0; i < files.length; i++) {
			File f = files[i];
			if (f.isDirectory() && listChild) {
				map.putAll(getDirMD5(f, listChild));
			} else {
				md5 = getFileMD5(f);
				if (md5 != null) {
					map.put(f.getPath(), md5);
				}
			}
		}
		return map;
	}
}
package cn.jerryhouse.util.dup_files;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public abstract class LineReaderProcessor extends FileProcessor {
	private long totalFileCount = 0;
	private long processedFileCount = 0;
	public void processFiles(File[] dirs) throws Exception {
		for (File file : dirs) {
			processFile(file);
		}
	}

	public void processFile(File file) throws Exception {
		if (file.isFile()) {
			if (isFileAccepted(file)) {
				handleFile(file);
			}
		} else {
			File[] files = file.listFiles();
			for (File fileInDir : files) {
				processFile(fileInDir);
			}
		}
	}

	protected boolean isFileAccepted(File file) throws Exception {
		return true;
	}

	protected void handleFile(File file)
	{
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			String line;
			while((line=br.readLine())!=null)
			{
				readLine(file,line);
			}
			br.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	protected abstract void readLine(File file,String line);

	public long getTotalFileCount() {
		return totalFileCount;
	}

	public long getProcessedFileCount() {
		return processedFileCount;
	}
}
package cn.jerryhouse.util.dup_files;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.UUID;

public abstract class LineUpdateProcessor extends FileProcessor {
	private long totalFileCount = 0;
	private long processedFileCount = 0;
	private String NEW_LINE = System.getProperty("line.separator");
	public void processFiles(File[] dirs) throws Exception {
		for (File file : dirs) {
			processFile(file);
		}
	}

	public void processFile(File file) throws Exception {
		if (file.isFile()) {
			if (isFileAccepted(file)) {
				handleFile(file);
			}
		} else {
			File[] files = file.listFiles();
			for (File fileInDir : files) {
				processFile(fileInDir);
			}
		}
	}

	protected boolean isFileAccepted(File file) throws Exception {
		return true;
	}

	protected void handleFile(File file)
	{
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			File tmpFile = new File(tmpFilePath(file));
			BufferedWriter bw = new BufferedWriter(new FileWriter(tmpFile));
			String line;
			while((line=br.readLine())!=null)
			{
				String updatedLine = updateLine(file,line);
				bw.write(updatedLine+NEW_LINE);
			}
			br.close();
			bw.close();
			file.delete();
			tmpFile.renameTo(file);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String tmpFilePath(File file)
	{
		String dir = file.getParent();
		String filePath = dir+""+getUniqFileName();
		return filePath;
	}

	private String getUniqFileName()
	{
		return UUID.randomUUID().toString();
	}
	protected abstract String updateLine(File file,String line);

	public long getTotalFileCount() {
		return totalFileCount;
	}

	public long getProcessedFileCount() {
		return processedFileCount;
	}
}

简单測试代码:

package cn.jerryhouse.util.dup_files.test;

import java.io.File;

import org.junit.Test;

import cn.jerryhouse.util.dup_files.ClassDupFinder;
import cn.jerryhouse.util.dup_files.FileDupFinder;
import cn.jerryhouse.util.dup_files.JarFileDupFinder;

public class DupTest {

	@Test
	public void testJarFiles() {
		try {
			File[] files = new File[1];
			files[0] = new File("E:\\workspace\\yinxing");
			JarFileDupFinder dupFinder = new JarFileDupFinder();
			dupFinder.processFiles(files);
			dupFinder.analyseResult();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Test
	public void testFileDup() {
		try {
			File[] files = new File[1];
			files[0] = new File("E:\\workspace\\yinxing");
			FileDupFinder classDupFinder = new FileDupFinder();
			classDupFinder.processFiles(files);
			classDupFinder.analyseResult();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testClassDup() {
		try {
			File[] files = new File[1];
			files[0] = new File("E:\\workspace\\yinxing");
			ClassDupFinder classDupFinder = new ClassDupFinder();
			classDupFinder.processFiles(files);
			classDupFinder.analyseResult();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

注:依赖jar包asm.jar。



时间: 2024-10-13 00:42:43

java查找反复类/jar包/普通文件的相关文章

java查找重复类/jar包/普通文件

开发web应用时,有时更新了类却没有生效,其实是因为jboss/tomcat中其他发布包下有同名类(包括全路径都相同). 于是萌发了做个程序来检查指定目录是否存在重复类(通过asm从类文件中取类的全路径),扩展开来,还支持查找重复的文件(按文件md5进行比较),重复的jar文件. 主要代码如下: 简单测试代码: package cn.jerryhouse.util.dup_files.test; import java.io.File; import org.junit.Test; import

Java实现动态修改Jar包内文件内容

import java.io.*; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; /** * jarPath: jar包所在路径 * jarFilePath: jar中想要修改文件所在

Java读取jar包资源文件

把java项目打包成jar包,如果jar包中存在资源文件需要访问,需要采取stream的形式访问,可以调用getResourceAsStream()方法,而不能采用路径的方式访问(文件已经被打到jar里面了,不符合路径的).使用getResourceAsStream()方法文件可以有两种方式存放: (1)文件存放在src的类路径下. (2)文件存放在资源文件夹下面,通过Build Path-Use as Source Folder来把普通文件夹变成资源文件夹. 如图,把testA打包成jar包,

Java中常见的jar包的用途

jar包用途  axis.jar   SOAP引擎包  commons-discovery-0.2.jar   用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期管理的常用方法.  jaxrpc.jar     Axis运行所需要的组件包  saaj.jar 创建到端点的点到点连接的方法.创建并处理SOAP消息和附件的方法,以及接收和处理SOAP错误的方法.    wsdl4j-1.5.1.jar Axis运行所需要的组件包  activation.jar JAF框架的jar

java中最常用jar包的用途说明

java中最常用jar包的用途说明,适合初学者 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期管理的常用方法. jaxrpc.jar Axis运行所需要的组件包 saaj.jar 创建到端点的点到点连接的方法.创建并处理SOAP消息和附件的方法,以及接收和处理SOAP错误的方法.   wsdl4j-1.5.1.jar Axis运行所需要的组件包 activation.ja

Java Service Wrapper将jar包安装成Windows服务

刚接触java,第一次使用Java开发windows服务,也是刚不久看了SSM框架 简直也是一头雾水,不过只要用心理解,其实很简单,下面有详细的步骤,包学包会 在windows上运行jar包,需要在工作目录下使用命令行运行jar包,这样会出现一个命令行窗口 而且这个命令行窗口有可能会不小心被关闭,且服务器启动后需要人为去点击开启 对于有些服务性的程序来说,我们需要将其部署为windows服务,在系统启动的时候自动启动 后来研究了两种方式: 1.使用 JavaService.exe 安装jar包

Java学习-039-源码 jar 包的二次开发扩展实例(源码修改)

最近在使用已有的一些 jar 包时,发现有些 jar 包中的一些方法无法满足自己的一些需求,例如返回固定的格式,字符串处理等等,因而需要对原有 jar 文件中对应的 class 文件进行二次开发扩展,并重新打包文件,替换原有的 jar 文件,满足测试开发自身的需求. 下面以修改 eclipse 默认注释中的 ${date} 和 ${time} 对应的返回样式(如下图所示),进行实例说明. 整个二次开发的过程如下所示: 0.未修改之前,生成注释的日期.时间显示格式如下所示: 1.获取对应的 jar

Redis(Windows安装方法与Java调用实例 &amp; 配置文件参数说明 &amp; Java使用Redis所用Jar包 &amp; Redis与Memcached的区别)

Windows下Redis的安装使用 0.前言 因为是初次使用,所以是在windows下进行安装和使用,参考了几篇博客,下面整理一下 1.安装Redis 官方网站:http://redis.io/ 官方下载:http://redis.io/download 可以根据需要下载不同版本 windows版:https://github.com/MSOpenTech/redis github的资源可以ZIP直接下载的(这个是给不知道的同学友情提示下) 下载完成后 可以右键解压到 某个硬盘下 比如D:\R

Java项目导出为jar包+导出第三方jar包+使用命令行调用+传参

Java项目导出为jar包+导出第三方jar包+使用命令行调用+传参 一.打包 情况1:不需要向程序传参数,并且程序没有使用第三方jar包 Eclipse上导出jar: 然后选择一个java文件作为入库,需要带main()主函数: 情况2:向程序传参数,并且程序没有使用第三方jar包 这种情形下打包和情况1是一样的 情况3:程序使用了第三方jar包 这种情况下的打包要复杂一些,需要把第三方jar包一起导出,可以使用eclipse的插件fat jar,很简便,但是fat jar只支持eclipse