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。




转载于:https://www.cnblogs.com/jerry1999/p/4175924.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值