C#實(shí)現(xiàn)高性能文件批量處理器的示例代碼
一、使用場景
文件批量處理器是用于我工作中的以下場景:
- 數(shù)字資產(chǎn)管理:對海量圖片/視頻進(jìn)行統(tǒng)一重命名(如20230319_客戶名_產(chǎn)品序列號.jpg)
- 數(shù)據(jù)遷移工程:將數(shù)萬份.doc文檔批量轉(zhuǎn)換為PDF格式并生成校驗(yàn)碼
- 日志文件處理:通過正則表達(dá)式篩選特定日期(如error_2025*.log)的日志文件進(jìn)行壓縮歸檔
- 安全審計(jì)場景:計(jì)算文件的SHA256哈希值驗(yàn)證數(shù)據(jù)完整性
二、設(shè)計(jì)亮點(diǎn)與實(shí)現(xiàn)方案
1. 核心架構(gòu)設(shè)計(jì)
/// <summary>
/// 文件批處理核心類(線程安全設(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>
/// 啟動多線程處理隊(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á)式過濾系統(tǒng)
/// <summary>
/// 獲取匹配正則的文件列表(參考網(wǎng)頁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>
/// 文件批量處理器核心類(線程安全)
/// 技術(shù)亮點(diǎn):
/// 1. 多線程流水線處理
/// 2. 正則表達(dá)式文件過濾
/// 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>
/// 文件名正則過濾模式
/// </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ì)列(支持正則過濾)
/// </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>
/// 啟動批量處理流程
/// </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)建新文件名(支持動態(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ù)對象
/// </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盤Images目錄下所有匹配文件 processor.EnqueueFiles(@"D:\Images");
步驟3:執(zhí)行批量處理
// 執(zhí)行重命名+格式轉(zhuǎn)換
processor.ProcessFiles(
renamePattern: "converted_{name}_{timestamp}.webp",
mode: ProcessMode.Both
);
步驟4:驗(yàn)證處理結(jié)果
日志會打印:
======== 處理完成 ========
原文件: 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VS2019下安裝和破解?DevExpress?19.2?插件的詳細(xì)教程
這篇文章主要介紹了VS2019?安裝并破解?DevExpress?19.2?插件的詳細(xì)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
利用C#實(shí)現(xiàn)批量圖片格式轉(zhuǎn)換功能
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)批量圖片格式轉(zhuǎn)換功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-12-12
C#實(shí)現(xiàn)將聊天數(shù)據(jù)發(fā)送加密
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)將聊天數(shù)據(jù)發(fā)送加密的功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12
C#零基礎(chǔ)開發(fā)中最重要的概念總結(jié)
這篇文章主要為大家詳細(xì)介紹了C#零基礎(chǔ)開發(fā)中最重要的一些概念,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,需要的可以參考一下2023-02-02
C#科學(xué)繪圖之使用scottPlot繪制多個(gè)圖像
ScottPlot是基于.Net的一款開源免費(fèi)的交互式可視化庫,支持Winform和WPF等UI框架,本文主要為大家詳細(xì)介紹了如何使用scottPlot實(shí)現(xiàn)繪制多個(gè)圖像,需要的可以參考下2023-12-12
C#中Convert.ToDecimal()報(bào)錯問題的解決
這篇文章主要給大家介紹了關(guān)于C#中Convert.ToDecimal()報(bào)錯問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08

