signed

QiShunwang

“诚信为本、客户至上”

基于MD5的一个文件监控程序

2021/4/26 19:34:55   来源:

基于MD5的一个文件系统监控FileMoniter

又是一篇因为不会做老师布置的作业而自己补习总结的一个篇blog

T_T

题目是基于FileMonitor框架编写代码实现文件系统监控,集成文件MD5码提取功能和文件MD5码与恶意软件特征码比对功能,对新增修改的文件进行检测。

说实话,我是真不知道FileMonitor框架是什么,网上搜到了也看不懂,悲哀ing

然后自己依照网上一个容易看懂的一点的代码写了一个(目前的版本,可能会做修改)

大佬的代码:Java:基于MD5的文件监听程序 - JYRoy - 博客园 (cnblogs.com)

(吐槽一下,这个代码真的就透露出一股python的味道,但还是很感谢,学到了很多知识)

参考后我自己写出的代码在最底下

总结一下这次敲代码学到的知识

1.File类

平成时候io流FileinputStream之类的用的真的很多,但我看到大佬代码中的File的用法真的是愣了一下,我是废物。

看了文档,File类貌似很有用的,于是自己学了总结了几个有用的方法

File file = new File(pathname)//这是一个有参构造,参数是文件路径,可以是具体的文件也可以是文件夹
//File 更应该叫做一个路径,文件路径或者文件夹路径。 
  • file.exists()方法,返回一个boolean值,用来判断该文件对象是否存在

  • file.list()方法,返回一个String的数组,返回指定目录下所有文件或者文件夹的名称(仅仅就是返回名称数组)

  • file.listFiles()方法,返回一个File的数组,返回指定目录下所有文件或文件夹的File数组

  • file.getName()方法,返回一个String对象,返回文件的名称

  • file.getAblsoulutePath()方法,返回String对象,获取文件的绝对路径

2.String类中的indexOf方法

我一直做那种算法题就不是很喜欢用java(学的不是很好,而且python是真的香),以前也是真不知道,string类有indexOf这个方法,可以很便易的判断字符串中是否含有某元素,并返回索引。

public class stringIndexOf {
    public static void main(String[] args) {
        String s ="ghsadfh";
        System.out.println(s.indexOf("s"));//返回2
        System.out.println(s.indexOf('s'));//返回2
        System.out.println(s.indexOf("hs"));//返回1
        System.out.println(s.indexOf("ghsadfh"));//返回0
        System.out.println(s.indexOf("sahasodfho"));//不存在就会返回-1
    }
}

3. 获取当前时间并转化为yyyy-MM-dd HH:mm:ss格式

有关时间的java类,我还真是一个也没学…

学习的bolg

方法一(线程不安全)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new new Date();
String time = sdf.format(new);

方法二(建议使用)

String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
    // yyyy-MM-dd HH:mm:ss.SSS  ---> 年-月-日 时-分-秒-毫秒   (想删掉哪个小部分就直接删掉哪个小部分)

4.代码实现

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

public class FileMonitor{
    Map<String,String> hashMap = new HashMap<>();
    public static void main(String[] args) throws Exception {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入要监测的文件夹的路径:");
        String dir = scan.next();
        System.out.println("开始初始化文件");//存储当前记录当前所有文件,和其hash码到hashmap中
        Map<String,String> hashMap = new HashMap<>();
        List<String> fileNames = new ArrayList<>();
        init(dir,hashMap,fileNames);
        System.out.println(hashMap);
        System.out.println("文件监测系统开始!!!!!!");
        iteratorPath(dir,hashMap);
    }
    //初始化,获取目标文件中所有文件的文件名及其对应的hash码
    public static void init(String dir,Map<String,String> hashMap,List<String> fileNames) throws Exception {
        File file = new File(dir);
        File[] files = file.listFiles();
        if(file!=null){
            for (File f : files) {
                if(f.isFile()){
                    fileNames.add(f.getName());
                    hashMap.put(f.getName(),getMD5(f.getAbsolutePath()));
                }else if(f.isDirectory()){
                    init(f.getAbsolutePath(),hashMap,fileNames);
                }
            }
        }

    }
    //监测文件(目前比较垃圾T^T,只能检测新增文件,和修改文件的行为,一旦删除文件就GG
    public static void iteratorPath(String dir,Map<String,String> hashMap) throws Exception {
        while(true){
            List<String> pathName = new ArrayList<>(); //存放文件名
            File file = new File(dir);
            File[] files = file.listFiles();
            if(file!=null){
                for (File f : files) {
                    pathName.add(f.getName());//存储文件名
                    String filePath = f.getAbsolutePath();
                    String hash = getMD5(filePath);//获取当前文件的hash码
                    if(hashMap.get(f.getName())==null){
                        System.out.println("文件夹:"+dir+"中新建文件:     "+f.getName()+"!   时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                        hashMap.put(f.getName(),hash);
                    }
                    if(!hashMap.get(f.getName()).equals(hash)){
                        System.out.println("文件夹:"+dir+"中的文件:       "+f.getName()+"被修改! 时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                        hashMap.put(f.getName(),hash);
                    }
                }
            }
            for (String key : hashMap.keySet()) {
                if(!pathName.contains(key)){
                    System.out.println("文件夹:"+dir+"中的文件:           "+key+"被删除!时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    hashMap.remove(key);
                }
            }
        }
    }

    //获取文件MD5加密后的hash码
    private static String getMD5(String fileName) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("MD5");

        FileInputStream fis = new FileInputStream(fileName);
        BufferedInputStream bis = new BufferedInputStream(fis);
        int len;
        byte[] buffer = new byte[2048];
        while((len=bis.read())!=-1){
            digest.update(buffer,0,len);
        }
        byte[] digestBytes = digest.digest();
        fis.close();
        return toHex(digestBytes);
    }

    //将字节数组转16进制的字符串
    private static String toHex(byte[] bytes){
        StringBuffer sb = new StringBuffer();
        for (byte b : bytes) {
            String s = Integer.toHexString(b & 0xff);
            if(s.length()==1){
                s="0"+s;
            }
            sb.append(s);
        }
        return sb.toString();
    }
}

简单说一下自己这个代码吧。

目前看有很多需要改进的,如果有需要用的话,建议dir路径(就是选的文件夹)里面的文件不要太多,也最好不要有空文件夹。

测试时,能给你检测到被改动的文件,和新增的文件(别新增文件夹)。关于删除文件额,我会在短时间内把这个功能加上去。

最后,就这样了。

(由于我很菜,若上述我写的有问题,欢迎指教!!)

^_^!