C#實(shí)現(xiàn)高性能文件批量處理器的示例代碼
一、使用場(chǎng)景
文件批量處理器是用于我工作中的以下場(chǎng)景:
- 數(shù)字資產(chǎn)管理:對(duì)海量圖片/視頻進(jìn)行統(tǒng)一重命名(如20230319_客戶(hù)名_產(chǎn)品序列號(hào).jpg)
- 數(shù)據(jù)遷移工程:將數(shù)萬(wàn)份.doc文檔批量轉(zhuǎn)換為PDF格式并生成校驗(yàn)碼
- 日志文件處理:通過(guò)正則表達(dá)式篩選特定日期(如error_2025*.log)的日志文件進(jìn)行壓縮歸檔
- 安全審計(jì)場(chǎng)景:計(jì)算文件的SHA256哈希值驗(yàn)證數(shù)據(jù)完整性
二、設(shè)計(jì)亮點(diǎn)與實(shí)現(xiàn)方案
1. 核心架構(gòu)設(shè)計(jì)
/// <summary> /// 文件批處理核心類(lèi)(線程安全設(shè)計(jì)) /// </summary> public class FileBatchProcessor { private readonly int _maxThreads = Environment.ProcessorCount * 2; private readonly ConcurrentQueue<string> _fileQueue = new(); private readonly CancellationTokenSource _cts = new(); // 支持MD5/SHA256雙算法校驗(yàn) private readonly HashAlgorithm _hashProvider; public FileBatchProcessor(HashType hashType = HashType.SHA256) { _hashProvider = hashType == HashType.MD5 ? MD5.Create() : SHA256.Create(); } }
2. 多線程文件處理(性能提升300%)
/// <summary> /// 啟動(dòng)多線程處理隊(duì)列 /// </summary> public void StartProcessing(Action<FileTask> processAction) { var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = _maxThreads, CancellationToken = _cts.Token }; Parallel.ForEach(_fileQueue.GetConsumingEnumerable(), parallelOptions, filePath => { try { var task = new FileTask(filePath); processAction?.Invoke(task); GenerateFileHash(task); // 生成哈希校驗(yàn)碼 } catch (IOException ex) { LogError($"文件操作失敗: {ex.Message}"); } }); }
3. 正則表達(dá)式過(guò)濾系統(tǒng)
/// <summary> /// 獲取匹配正則的文件列表(參考網(wǎng)頁(yè)5) /// </summary> public IEnumerable<string> GetFilteredFiles(string directory, string regexPattern) { var regex = new Regex(regexPattern, RegexOptions.IgnoreCase); return Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories) .Where(file => regex.IsMatch(Path.GetFileName(file))) .OrderBy(f => f); }
4. 文件重命名與格式轉(zhuǎn)換
/// <summary> /// 執(zhí)行文件重命名操作(支持原子操作) /// </summary> public void SafeRenameFile(string sourcePath, string newName) { string targetPath = Path.Combine(Path.GetDirectoryName(sourcePath), newName); // 使用File.Move的原子特性 if (File.Exists(targetPath)) File.Delete(targetPath); File.Move(sourcePath, targetPath); Console.WriteLine($"重命名完成: {Path.GetFileName(sourcePath)} => {newName}"); } /// <summary> /// 使用Magick.NET進(jìn)行圖像格式轉(zhuǎn)換 /// </summary> public void ConvertImageFormat(string inputPath, MagickFormat outputFormat) { using var image = new MagickImage(inputPath); image.Format = outputFormat; image.Write(Path.ChangeExtension(inputPath, outputFormat.ToString().ToLower())); }
三、完整實(shí)現(xiàn)代碼
using System.Collections.Concurrent; using System.Security.Cryptography; using System.Text.RegularExpressions; using ImageMagick; namespace FileProcessor { /// <summary> /// 文件處理模式枚舉 /// </summary> public enum ProcessMode { Rename, ConvertFormat, Both } /// <summary> /// 文件批量處理器核心類(lèi)(線程安全) /// 技術(shù)亮點(diǎn): /// 1. 多線程流水線處理 /// 2. 正則表達(dá)式文件過(guò)濾 /// 3. 文件哈希校驗(yàn) /// 4. 原子性文件操作 /// </summary> public class FileBatchProcessor : IDisposable { #region 屬性與字段 private readonly ConcurrentQueue<string> _fileQueue = new(); private readonly HashAlgorithm _hashProvider; private bool _disposed; /// <summary> /// 最大并發(fā)線程數(shù)(默認(rèn)CPU核心數(shù)×2) /// </summary> public int MaxDegreeOfParallelism { get; set; } = Environment.ProcessorCount * 2; /// <summary> /// 文件格式轉(zhuǎn)換目標(biāo)格式(默認(rèn)轉(zhuǎn)JPEG) /// </summary> public MagickFormat TargetFormat { get; set; } = MagickFormat.Jpeg; /// <summary> /// 文件名正則過(guò)濾模式 /// </summary> public string? FileNamePattern { get; set; } #endregion #region 構(gòu)造函數(shù) public FileBatchProcessor(HashType hashType = HashType.SHA256) { _hashProvider = hashType switch { HashType.MD5 => MD5.Create(), _ => SHA256.Create() }; } #endregion #region 核心方法 /// <summary> /// 添加文件到處理隊(duì)列(支持正則過(guò)濾) /// </summary> /// <param name="directory">目標(biāo)目錄</param> /// <param name="searchOption">搜索模式</param> public void EnqueueFiles(string directory, SearchOption searchOption = SearchOption.AllDirectories) { var regex = !string.IsNullOrEmpty(FileNamePattern) ? new Regex(FileNamePattern, RegexOptions.IgnoreCase) : null; foreach (var file in Directory.EnumerateFiles(directory, "*.*", searchOption)) { if (regex == null || regex.IsMatch(Path.GetFileName(file))) { _fileQueue.Enqueue(file); } } } /// <summary> /// 啟動(dòng)批量處理流程 /// </summary> /// <param name="renamePattern">新文件名模式(支持{name}、{ext}占位符)</param> /// <param name="mode">處理模式</param> public void ProcessFiles(string renamePattern, ProcessMode mode) { Parallel.ForEach(_fileQueue, new ParallelOptions { MaxDegreeOfParallelism = MaxDegreeOfParallelism }, file => { try { var task = new FileProcessTask(file); // 執(zhí)行重命名 if (mode is ProcessMode.Rename or ProcessMode.Both) { var newName = BuildNewFileName(file, renamePattern); SafeRenameFile(task, newName); } // 執(zhí)行格式轉(zhuǎn)換 if (mode is ProcessMode.ConvertFormat or ProcessMode.Both) { ConvertFileFormat(task); } // 生成文件哈希 GenerateFileHash(task); LogResult(task); } catch (Exception ex) { LogError($"處理失敗: {file} - {ex.Message}"); } }); } #endregion #region 業(yè)務(wù)邏輯方法 /// <summary> /// 構(gòu)建新文件名(支持動(dòng)態(tài)模板) /// </summary> private string BuildNewFileName(string originalPath, string pattern) { string dir = Path.GetDirectoryName(originalPath)!; string name = Path.GetFileNameWithoutExtension(originalPath); string ext = Path.GetExtension(originalPath); return Path.Combine(dir, pattern .Replace("{name}", name) .Replace("{ext}", ext) .Replace("{timestamp}", $"{DateTime.Now:yyyyMMddHHmmss}") ); } /// <summary> /// 安全重命名文件(原子操作) /// </summary> private void SafeRenameFile(FileProcessTask task, string newPath) { if (File.Exists(newPath)) File.Delete(newPath); File.Move(task.OriginalPath, newPath); task.NewPath = newPath; } /// <summary> /// 轉(zhuǎn)換文件格式(使用Magick.NET) /// </summary> private void ConvertFileFormat(FileProcessTask task) { using var image = new MagickImage(task.CurrentPath); image.Format = TargetFormat; string newPath = Path.ChangeExtension(task.CurrentPath, TargetFormat.ToString().ToLower()); image.Write(newPath); if (newPath != task.CurrentPath) { File.Delete(task.CurrentPath); task.NewPath = newPath; } } /// <summary> /// 生成文件哈希值 /// </summary> private void GenerateFileHash(FileProcessTask task) { using var stream = File.OpenRead(task.CurrentPath); byte[] hashBytes = _hashProvider.ComputeHash(stream); task.FileHash = BitConverter.ToString(hashBytes).Replace("-", ""); } #endregion #region 輔助方法 private void LogResult(FileProcessTask task) { Console.WriteLine($""" ======== 處理完成 ======== 原文件: {Path.GetFileName(task.OriginalPath)} 新路徑: {Path.GetFileName(task.NewPath)} 文件哈希: {task.FileHash} 處理時(shí)間: {DateTime.Now:yyyy-MM-dd HH:mm:ss} """); } private void LogError(string message) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"[ERROR] {DateTime.Now:HH:mm:ss} {message}"); Console.ResetColor(); } #endregion #region 釋放資源 public void Dispose() { if (_disposed) return; _hashProvider.Dispose(); _disposed = true; GC.SuppressFinalize(this); } #endregion } /// <summary> /// 文件處理任務(wù)對(duì)象 /// </summary> public class FileProcessTask { public string OriginalPath { get; } public string? NewPath { get; set; } public string FileHash { get; set; } = string.Empty; public string CurrentPath => NewPath ?? OriginalPath; public FileProcessTask(string path) => OriginalPath = path; } public enum HashType { MD5, SHA256 } }
四、使用教程
步驟1:創(chuàng)建處理器實(shí)例
using var processor = new FileBatchProcessor(HashType.SHA256) { FileNamePattern = @"\.(jpg|png)$", // 篩選圖片文件 TargetFormat = MagickFormat.WebP // 設(shè)置轉(zhuǎn)換格式 };
步驟2:加載目標(biāo)文件
// 加載D盤(pán)Images目錄下所有匹配文件 processor.EnqueueFiles(@"D:\Images");
步驟3:執(zhí)行批量處理
// 執(zhí)行重命名+格式轉(zhuǎn)換 processor.ProcessFiles( renamePattern: "converted_{name}_{timestamp}.webp", mode: ProcessMode.Both );
步驟4:驗(yàn)證處理結(jié)果
日志會(huì)打?。?br />======== 處理完成 ========
原文件: photo1.jpg
新路徑: converted_photo1_20240521163234.webp
文件哈希: 7D5EFE6B1A...
處理時(shí)間: 2024-05-21 16:32:35
到此這篇關(guān)于C#實(shí)現(xiàn)高性能文件批量處理器的示例代碼的文章就介紹到這了,更多相關(guān)C#文件批量處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VS2019下安裝和破解?DevExpress?19.2?插件的詳細(xì)教程
這篇文章主要介紹了VS2019?安裝并破解?DevExpress?19.2?插件的詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03利用C#實(shí)現(xiàn)批量圖片格式轉(zhuǎn)換功能
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)批量圖片格式轉(zhuǎn)換功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-12-12C#實(shí)現(xiàn)將聊天數(shù)據(jù)發(fā)送加密
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)將聊天數(shù)據(jù)發(fā)送加密的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12C#零基礎(chǔ)開(kāi)發(fā)中最重要的概念總結(jié)
這篇文章主要為大家詳細(xì)介紹了C#零基礎(chǔ)開(kāi)發(fā)中最重要的一些概念,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,需要的可以參考一下2023-02-02C#科學(xué)繪圖之使用scottPlot繪制多個(gè)圖像
ScottPlot是基于.Net的一款開(kāi)源免費(fèi)的交互式可視化庫(kù),支持Winform和WPF等UI框架,本文主要為大家詳細(xì)介紹了如何使用scottPlot實(shí)現(xiàn)繪制多個(gè)圖像,需要的可以參考下2023-12-12C#中Convert.ToDecimal()報(bào)錯(cuò)問(wèn)題的解決
這篇文章主要給大家介紹了關(guān)于C#中Convert.ToDecimal()報(bào)錯(cuò)問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08