Unity编辑器小工具——文件查重(MD5)

Unity编辑器小工具——文件查重(MD5)

算法思想:
在Unity中,每一个不同资源、文件所生成MD5码是不同的,但是相同文件,路径不同、文件名不同的同一类文件的MD5码是相同的,所以可以通过生成每个文件的MD5来判断文件是否是重复的。

具体脚本代码如下:

using UnityEngine;
using System.Collections;
using System.IO;
using UnityEditor;
using System.Security.Cryptography;
using System;
using System.Linq;

public class FindMD : MonoBehaviour {
    string[] files;
    [MenuItem("Assets/Find Files MD5")]
    public static void Find()
    {
        int flag = 0;

        string[] files = Directory.GetFiles("Assets/", "*.*", SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            if (files[i].EndsWith(".meta"))
            {
                continue;
            }
            //加载进度条
            EditorUtility.DisplayCancelableProgressBar("匹配资源中", files[i], ((float)i / (float)files.Length));
            for (int j = 0; j < files.Length; j++)
            {
                if (files[j].EndsWith(".meta"))
                {
                    continue;
                }
                if (i != j && getFileMD5(files[i]) == getFileMD5(files[j]))
                {
                    Debug.LogError(files[i] + "   and    " + files[j] + "have the same md5");
                    flag = 1;
                }
            }
        }
        //清除进度条
        EditorUtility.ClearProgressBar();

        if (flag == 0)
        {
            Debug.Log("No files are equal");
        }
    }


    public static string getFileMD5(string filePath)
    {
        //将文件路径转化为文件流
        FileStream fs = new FileStream(filePath, FileMode.Open);
        byte[] data = new byte[(int)fs.Length];

        //读文件
        fs.Read(data, 0, (int)fs.Length);
        fs.Close();

        //通过MD5接口生成MD5码(获得的是Hash一个字节数组)MD5加密
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] result = md5.ComputeHash(data);

        //将获得的Hash字节数组转换为字符串
        string fileMD5 = "";
        foreach (byte b in result)
        {
            fileMD5 += Convert.ToString(b, 16);
        }

        //fs.Close();
        return fileMD5;

    }
}

注意要点:
1. 在Unity下,每个文件都有对应的meta文件,但是对于文件查重来说并没有什么实际的用途,所以在文件读取对比时可以跳过
2. 在进行meta文件筛选时,有两种办法,一种如脚本中一样,在要比较md5码前,判断是否为meta文件。另一种为在Directory.GetFiles() 时,通过拉曼达表达式来进行筛选,但是在使用拉曼达表达式时,还要使用foreach循环进行查找,所以放弃了后种方法
3. 由于使用了双层for循环,所以查找速率较低,后通过如下脚本进行了改进

改进脚本如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
using System.Security.Cryptography;
using System;
using System.Linq;

public class FindMD_2 : MonoBehaviour {

    string[] files;
    [MenuItem("Assets/Find Files MD5")]
    public static void Find()
    {

        int flag = 0;
        Dictionary<string, string> MDdic = new Dictionary<string, string>();
        string[] files = Directory.GetFiles("Assets/", "*.*", SearchOption.AllDirectories);
        string file_2 = "";
        for (int i = 0; i < files.Length; i++)
        {
            string filemd5 = getFileMD5(files[i]);
            if (files[i].EndsWith(".meta"))
            {
                continue;
            }

            //加载进度条
            EditorUtility.DisplayCancelableProgressBar("匹配资源中", files[i], ((float)i / (float)files.Length));
            if (MDdic.ContainsValue(filemd5))
            {

                foreach (string key in MDdic.Keys)
                {
                    if (MDdic[key].Equals(filemd5))
                    {
                        file_2 = key;
                    }
                }

                Debug.LogError(files[i] + "   and    " + file_2.ToString() + "have the same md5");
            }
            else
            {
                MDdic.Add(files[i], filemd5);
            }

        }


        if (flag == 0)
        {
            Debug.Log("No files are equal");
        }
    }


    public static string getFileMD5(string filePath)
    {
        //将文件路径转化为文件流
        FileStream fs = new FileStream(filePath, FileMode.Open);
        byte[] data = new byte[(int)fs.Length];

        //读文件
        fs.Read(data, 0, (int)fs.Length);
        fs.Close();

        //通过MD5接口生成MD5码(获得的是Hash一个字节数组)MD5加密
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] result = md5.ComputeHash(data);

        //将获得的Hash字节数组转换为字符串
        string fileMD5 = "";
        foreach (byte b in result)
        {
            fileMD5 += Convert.ToString(b, 16);
        }

        //fs.Close();
        return fileMD5;

    }
}

猜你喜欢

转载自blog.csdn.net/ZNWhahaha/article/details/81273446