欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET根據(jù)文件的哈希值篩選重復(fù)文件的實(shí)現(xiàn)思路

 更新時(shí)間:2025年03月14日 10:19:41   作者:醉酒的李白、  
文章介紹了文件哈希值的概念,包括哈希算法、唯一性、固定長(zhǎng)度、不可逆性以及其在文件驗(yàn)證、數(shù)據(jù)完整性檢查、文件去重、密碼存儲(chǔ)等領(lǐng)域的應(yīng)用,接著,通過一個(gè)示例代碼說明了如何通過文件大小分組并比對(duì)哈希值來篩選出重復(fù)文件,感興趣的朋友一起看看吧

如題。先介紹下概念。

Q1. 文件的哈希值是什么?

文件的哈希值是通過特定的哈希算法對(duì)文件內(nèi)容進(jìn)行計(jì)算后得到的固定長(zhǎng)度的字符串(通常由數(shù)字和字母組成),它具有以下特點(diǎn)和相關(guān)信息:

  • 哈希算法:常見的用于計(jì)算文件哈希值的算法包括 MD5、SHA-1、SHA-256、SHA-512 等。不同算法的計(jì)算方式和生成的哈希值長(zhǎng)度不同。例如,MD5 算法生成的哈希值是 128 位(通常以 32 個(gè)十六進(jìn)制字符表示),SHA-256 算法生成的哈希值是 256 位(以 64 個(gè)十六進(jìn)制字符表示) 。
  • 唯一性:理論上,不同內(nèi)容的文件經(jīng)過哈希算法計(jì)算后,應(yīng)該得到不同的哈希值。這意味著如果兩個(gè)文件的哈希值相同,那么它們的內(nèi)容很可能是完全一樣的(雖然存在極小概率的哈希碰撞,即不同內(nèi)容產(chǎn)生相同哈希值,但這種情況非常罕見)。例如,在文件傳輸過程中,接收方可以計(jì)算接收到的文件的哈希值,并與發(fā)送方提供的原始文件哈希值進(jìn)行比較,以驗(yàn)證文件在傳輸過程中是否完整無損,沒有被篡改。
  • 固定長(zhǎng)度:無論文件的大小和內(nèi)容如何,使用特定哈希算法計(jì)算得到的哈希值長(zhǎng)度是固定的。例如,無論一個(gè)文本文件是幾 KB 還是幾 MB,使用 SHA-256 算法計(jì)算出的哈希值始終是 256 位。
  • 不可逆性:哈希計(jì)算是一種單向操作,即可以通過文件內(nèi)容計(jì)算出哈希值,但無法從哈希值反向推導(dǎo)出原始的文件內(nèi)容。這使得哈希值在數(shù)據(jù)存儲(chǔ)和安全驗(yàn)證等方面具有重要作用,比如在存儲(chǔ)用戶密碼時(shí),通常存儲(chǔ)的是密碼的哈希值,即使數(shù)據(jù)庫被攻擊,攻擊者也難以從哈希值還原出原始密碼。

哈希值在文件驗(yàn)證、數(shù)據(jù)完整性檢查、文件去重、密碼存儲(chǔ)等眾多領(lǐng)域都有廣泛應(yīng)用,是確保數(shù)據(jù)一致性和安全性的重要手段之一。

Q2. 比如一個(gè)文件 有1G大小,那么它的哈希值會(huì)多大?

文件哈希值的大小與文件本身的大小無關(guān),而是由所使用的哈希算法決定。

常見的哈希算法及其生成的哈希值大小如下:

  • MD5 算法:生成 128 位(16 字節(jié))的哈希值,通常以 32 個(gè)十六進(jìn)制字符表示。例如:d41d8cd98f00b204e9800998ecf8427e ,無論原文件是 1 字節(jié)還是 1GB 甚至更大,使用 MD5 算法計(jì)算出的哈希值固定是 128 位。
  • SHA-1 算法:產(chǎn)生 160 位(20 字節(jié))的哈希值,一般以 40 個(gè)十六進(jìn)制字符呈現(xiàn)。比如:da39a3ee5e6b4b0d3255bfef95601890afd80709 ,不管文件大小怎樣變化,SHA-1 算法得到的哈希值長(zhǎng)度不變。SHA-256 算法:輸出 256 位(32 字節(jié))的哈希值,以 64 個(gè)十六進(jìn)制字符展示。例如:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ,即使是 1GB 的大文件,其 SHA-256 哈希值依然是 256 位。
  • SHA-512 算法:生成 512 位(64 字節(jié))的哈希值,用 128 個(gè)十六進(jìn)制字符表示。如:cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e ,同樣不受文件大小影響。

所以,一個(gè) 1GB 大小的文件,其哈希值的大小取決于選擇的哈希算法,而不是文件自身的體積大小。

需求:客戶有200+份文件來源于不同的三方平臺(tái),但是客戶不確定是否有重復(fù)文件。可能來源不同但是文件相同??蛻粝MY出這些重復(fù)文件。供用戶搜索用,這樣用戶就只會(huì)搜出唯一的文件結(jié)果,而不是來源于不同渠道的相同文件。

實(shí)現(xiàn)思路:

先獲取所有文件的大小,并按照大小group by,這樣相同大小的文件就會(huì)在一組。文件大小不同一定不屬于相同文件,文件大小相同有可能屬于相同文件,也有可能是不同的文件剛好大小相等。按照這方式,遍歷所有相同大小的組。比對(duì)哈希值。文件大小不同的就不用比較了??隙ú皇窍嗤募?。

/*
代碼說明
FindDuplicateFilesGrouped 方法:
首先遍歷傳入的文件路徑數(shù)組,將每個(gè)文件的信息(Id、FileName、FileSize)封裝到 FileInfoEntity 對(duì)象中,并添加到 fileInfos 列表。
接著按文件大小對(duì) fileInfos 進(jìn)行分組,得到 sizeGroups。
針對(duì)每個(gè)大小組,計(jì)算組內(nèi)每個(gè)文件的哈希值,把具有相同哈希值的文件存到 hashGroups 字典里。
最后,將 hashGroups 中包含多個(gè)文件的組添加到 duplicateFileGroups 列表,該列表即為最終按組返回的重復(fù)文件結(jié)果。
通過這種方式,就能方便地找出所有重復(fù)文件,并將它們按組分類返回。
*/

FileComparisonTool.cs

//FileComparisonTool.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
namespace ConsoleApp1_CompareFiles
{
    // 文件實(shí)體類
    public class FileInfoEntity
    {
        public Guid Id { get; set; }
        public MemoryStream Stream { get; set; }
        public string FileName { get; set; }
        public long FileSize { get; set; }
    }
    // 文件比較工具類
    public class FileComparisonTool
    {
        public static string[] GetAllFilesInFolder(string folderPath)
        {
            try
            {
                // 獲取當(dāng)前文件夾下的所有文件
                string[] files = Directory.GetFiles(folderPath);
                // 獲取當(dāng)前文件夾下的所有子文件夾
                string[] subFolders = Directory.GetDirectories(folderPath);
                foreach (string subFolder in subFolders)
                {
                    // 遞歸調(diào)用獲取子文件夾下的所有文件
                    string[] subFiles = GetAllFilesInFolder(subFolder);
                    files = files.Concat(subFiles).ToArray();
                }
                return files;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"發(fā)生錯(cuò)誤: {ex.Message}");
                return new string[0];
            }
        }
        // 計(jì)算文件哈希值
        private static string CalculateHash(Stream stream)
        {
            using (SHA256 sha256 = SHA256.Create())
            {
                byte[] hashBytes = sha256.ComputeHash(stream);
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
            }
        }
        // 入?yún)⑹莾蓚€(gè)文件流,比較兩個(gè)文件
        public static bool CompareFiles(Stream stream1, Stream stream2)
        {
            stream1.Position = 0;
            stream2.Position = 0;
            string hash1 = CalculateHash(stream1);
            string hash2 = CalculateHash(stream2);
            return hash1 == hash2;
        }
        // 入?yún)⑹莾蓚€(gè)文件路徑,比較兩個(gè)文件
        public static bool CompareFiles(string filePath1, string filePath2)
        {
            using (FileStream stream1 = File.OpenRead(filePath1))
            using (FileStream stream2 = File.OpenRead(filePath2))
            {
                return CompareFiles(stream1, stream2);
            }
        }
        // 入?yún)⑹俏募窂降臄?shù)組,找出重復(fù)文件
        public static List<FileInfoEntity> FindDuplicateFiles(string[] filePaths)
        {
            var fileInfos = new List<FileInfoEntity>();
            foreach (var filePath in filePaths)
            {
                var fileInfo = new FileInfo(filePath);
                fileInfos.Add(new FileInfoEntity
                {
                    Id = Guid.NewGuid(),
                    FileName = filePath,
                    FileSize = fileInfo.Length
                });
            }
            var groups = fileInfos.GroupBy(f => f.FileSize);
            var duplicateFiles = new List<FileInfoEntity>();
            foreach (var group in groups)
            {
                if (group.Count() > 1)
                {
                    var hashes = new Dictionary<string, FileInfoEntity>();
                    foreach (var file in group)
                    {
                        using (FileStream stream = File.OpenRead(file.FileName))
                        {
                            string hash = CalculateHash(stream);
                            if (hashes.ContainsKey(hash))
                            {
                                if (!duplicateFiles.Contains(hashes[hash]))
                                {
                                    duplicateFiles.Add(hashes[hash]);
                                }
                                duplicateFiles.Add(file);
                            }
                            else
                            {
                                hashes[hash] = file;
                            }
                        }
                    }
                }
            }
            return duplicateFiles;
        }
        /*
        代碼說明
        FindDuplicateFilesGrouped 方法:
        首先遍歷傳入的文件路徑數(shù)組,將每個(gè)文件的信息(Id、FileName、FileSize)封裝到 FileInfoEntity 對(duì)象中,并添加到 fileInfos 列表。
        接著按文件大小對(duì) fileInfos 進(jìn)行分組,得到 sizeGroups。
        針對(duì)每個(gè)大小組,計(jì)算組內(nèi)每個(gè)文件的哈希值,把具有相同哈希值的文件存到 hashGroups 字典里。
        最后,將 hashGroups 中包含多個(gè)文件的組添加到 duplicateFileGroups 列表,該列表即為最終按組返回的重復(fù)文件結(jié)果。
        通過這種方式,就能方便地找出所有重復(fù)文件,并將它們按組分類返回。
        */
        // 入?yún)⑹俏募窂綌?shù)組,按組返回重復(fù)文件
        public static List<List<FileInfoEntity>> FindDuplicateFilesGrouped(string[] filePaths)
        {
            var fileInfos = new List<FileInfoEntity>();
            foreach (var filePath in filePaths)
            {
                var fileInfo = new FileInfo(filePath);
                fileInfos.Add(new FileInfoEntity
                {
                    Id = Guid.NewGuid(),
                    FileName = filePath,
                    FileSize = fileInfo.Length
                });
            }
            var sizeGroups = fileInfos.GroupBy(f => f.FileSize);
            var duplicateFileGroups = new List<List<FileInfoEntity>>();
            foreach (var sizeGroup in sizeGroups)
            {
                if (sizeGroup.Count() > 1)
                {
                    var hashGroups = new Dictionary<string, List<FileInfoEntity>>();
                    foreach (var file in sizeGroup)
                    {
                        using (FileStream stream = File.OpenRead(file.FileName))
                        {
                            string hash = CalculateHash(stream);
                            if (!hashGroups.ContainsKey(hash))
                            {
                                hashGroups[hash] = new List<FileInfoEntity>();
                            }
                            hashGroups[hash].Add(file);
                        }
                    }
                    foreach (var hashGroup in hashGroups.Values)
                    {
                        if (hashGroup.Count > 1)
                        {
                            duplicateFileGroups.Add(hashGroup);
                        }
                    }
                }
            }
            return duplicateFileGroups;
        }
    }
}
 

//

// Program.cs
// See https://aka.ms/new-console-template for more information
using ConsoleApp1_CompareFiles;
Console.WriteLine("Hello, World!");
string[] filePaths = { 
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\1.txt",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\2.txt",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\3.txt",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\4.xlsx",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\5.xlsx",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\6.docx",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\7.docx",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\8.jpeg",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\9.jpeg",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\捕獲 - 副本.PNG",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\捕獲.PNG",
    "C:\\Users\\Aa\\Desktop\\新建文件夾\\微信圖片_20250221165428.png",
};
string folderPath = @"C:\Users\Aa\Desktop\新建文件夾";
string[] allFiles = FileComparisonTool.GetAllFilesInFolder(folderPath);
var duplicateFileGroups = FileComparisonTool.FindDuplicateFilesGrouped(allFiles);
Console.WriteLine($"找到的重復(fù)文件組數(shù)量: {duplicateFileGroups.Count}");
foreach (var group in duplicateFileGroups)
{
    Console.WriteLine($"該組重復(fù)文件數(shù)量: {group.Count}");
    foreach (var file in group)
    {
        Console.WriteLine($"  文件 ID: {file.Id}, 文件名: {file.FileName}, 文件大小: {file.FileSize}");
    }
}

實(shí)現(xiàn)效果:

測(cè)試文件.txt文本的舉例子??梢钥吹近S框和紅框內(nèi)的都屬于相同文件。紅框和黃框內(nèi)的雖然字節(jié)數(shù)是一樣的,相同大小會(huì)group by到一組。但是hash值肯定是不同的。

到此這篇關(guān)于.NET下根據(jù)文件的哈希值篩選重復(fù)文件的文章就介紹到這了,更多相關(guān).net哈希值篩選重復(fù)文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Attribute/特性心得隨筆

    Attribute/特性心得隨筆

    從事asp.net工作的相關(guān)人員對(duì)Attribute并不陌生吧,本文就來為大家介紹下Attribute特性,下面有個(gè)不錯(cuò)的示例,喜歡的朋友感受下
    2013-11-11
  • .net core中的Authorization過濾器使用

    .net core中的Authorization過濾器使用

    這篇文章主要介紹了.net core中的Authorization過濾器使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • .NET Core中反解ObjectId

    .NET Core中反解ObjectId

    這篇文章主要介紹了.NET Core中實(shí)現(xiàn)ObjectId反解的方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-08-08
  • 收集學(xué)習(xí)asp.net比較完整的面向?qū)ο箝_發(fā)流程

    收集學(xué)習(xí)asp.net比較完整的面向?qū)ο箝_發(fā)流程

    如果你已經(jīng)有較多的面向?qū)ο箝_發(fā)經(jīng)驗(yàn),跳過以下這兩步 第一步:掌握一門.NET面向?qū)ο笳Z言第二步:對(duì).NET Framework類庫有一定的了解;在具備了OO基礎(chǔ)之后,以下是具體的學(xué)習(xí)ASP.NET技術(shù)步驟
    2012-12-12
  • asp.net實(shí)現(xiàn)XML文件讀取數(shù)據(jù)綁定到DropDownList的方法

    asp.net實(shí)現(xiàn)XML文件讀取數(shù)據(jù)綁定到DropDownList的方法

    這篇文章主要介紹了asp.net實(shí)現(xiàn)XML文件讀取數(shù)據(jù)綁定到DropDownList的方法,結(jié)合實(shí)例形式分析了asp.net針對(duì)xml文件操作及DropDownList控件的使用技巧,需要的朋友可以參考下
    2017-02-02
  • 從ASP.NET得到Microsoft Word文檔的代碼

    從ASP.NET得到Microsoft Word文檔的代碼

    這篇文章是應(yīng)在一個(gè)ASP.NET項(xiàng)目中建立Microsoft Word文檔的需要而寫的。本文描述了怎樣使用ASP.NET來創(chuàng)建和修改Microsoft Word文檔。
    2011-06-06
  • .net GridView分頁模板的實(shí)例代碼

    .net GridView分頁模板的實(shí)例代碼

    .net GridView分頁模板的實(shí)例代碼,對(duì)分頁代碼有興趣的朋友可以參考一下
    2013-03-03
  • 未處理的事件"PageIndexChanging" 之解決方案

    未處理的事件"PageIndexChanging" 之解決方案

    今天我寫一個(gè)小程序遇到這個(gè)問題,上網(wǎng)搜了一下,已經(jīng)有很好的解決方法了,以前都是拉控件自己生成,現(xiàn)在用代碼自己寫就出現(xiàn)了這個(gè)問題
    2008-07-07
  • WPF實(shí)現(xiàn)帶全選復(fù)選框的列表控件

    WPF實(shí)現(xiàn)帶全選復(fù)選框的列表控件

    這篇文章主要為大家詳細(xì)介紹了WPF實(shí)現(xiàn)帶全選復(fù)選框的列表控件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 解析ABP框架中的數(shù)據(jù)傳輸對(duì)象與應(yīng)用服務(wù)

    解析ABP框架中的數(shù)據(jù)傳輸對(duì)象與應(yīng)用服務(wù)

    ABP框架是基于ASP.NET的Web開發(fā)框架,在ABP中應(yīng)用服務(wù)將領(lǐng)域邏輯暴露給展現(xiàn)層,展現(xiàn)層通過傳入數(shù)據(jù)傳輸對(duì)象參數(shù)來調(diào)用應(yīng)用服務(wù),而這里我們就來解析ABP框架中的數(shù)據(jù)傳輸對(duì)象與應(yīng)用服務(wù)
    2016-06-06

最新評(píng)論