首页/新闻资讯/正文详情

C#自动清理过期文件:规则设计、核心代码与定时任务部署

发布时间:2026/9/26 14:11:02 来源:云帆数科 栏目:资讯中心
C#自动清理过期文件:规则设计、核心代码与定时任务部署
最近有朋友问我C# 能不能写个小工具自动扫描指定目录只保留最近 30 天的文件把过期文件删除掉。这个需求太常见了——程序跑几个月日志、临时导出文件、备份文件堆成山磁盘迟早被吃满。与其手动清理不如写一个自动删除过期文件的小工具。这篇文章会从规则设计、核心代码、测试验证一直聊到上线后的自动化与排错适合想在 Windows 环境里做定时清理的 C# 开发者也适合刚入门、想练手的读者。别看功能简单真正落地时你会发现“哪些文件算过期”“目录要不要递归”“文件被占用怎么办”都是需要提前拍板的事。我把自己写这个清理器过程中踩过的坑和验证思路完整整理出来希望能帮你少走点弯路。1. 这个需求从哪里来为什么“30天”成了标配1.1 日志和临时文件是如何吃掉磁盘的大多数长期运行的程序都有“越跑越胖”的毛病。以日志文件为例一个每天写几十 MB 日志的服务看起来不多但一个月下来就是几个 GB如果程序还定期导出报表、生成缓存、解压临时包磁盘占用会涨得更快。最麻烦的是这些文件一旦生成几乎没有业务逻辑会主动删除日积月累就成了“垃圾文件”。等到磁盘告警或服务异常才想起去翻目录、按时间排序、手动删除这时候往往为时已晚。有一次我负责的机器就是因为某个目录里堆了上千个临时文件导致系统盘被写满数据库直接罢工。那次之后我意识到这类问题不能靠“记性”必须在程序层面用一个自动清理机制兜底。1.2 手动清理的痛点与“自动清理器”的定位手动清理的痛点很直接耗时、容易误删、还带情绪。你说昨天还跑得好好的今天突然没了某个文件谁也说不清是不是清理时手抖了。自动清理器不是把文件一股脑删掉而是按照“保留最近 N 天”的规则把超过 N 天的文件找出来删除它在定位上更像是一个“磁盘空间的管家”。“30 天”这个数字在很多业务里算是个默认值。日志保留 30 天既能覆盖大多数排障需求又不至于让磁盘一直膨胀备份文件保留 30 天相当于给了“发现备份出问题”的缓冲期。当然不同场景可能需要 7 天、90 天、180 天所以实现时不要写死天数做成参数才是正经方案。理解了背景下一步要解决的不是怎么写File.Delete而是先把“什么算过期、什么不能删”的规则想清楚。2. 动手前先定规则过期判定、递归、只读这些边界想清楚2.1 用哪个时间戳判断“文件年龄”才靠谱C# 里获取文件时间有三个常用属性File.GetCreationTime()/FileInfo.CreationTimeFile.GetLastWriteTime()/FileInfo.LastWriteTimeFile.GetLastAccessTime()/FileInfo.LastAccessTime很多人第一反应是“创建时间不是最自然的吗”实际上并不总是好用。文件从备份恢复、被某些工具复制、甚至迁移到另一台机器后创建时间可能变成当前时间这会导致本来很老的文件被当成“新文件”保留下来。访问时间更不稳定因为每次读取都可能刷新它而且 Windows 出于性能考虑可能完全关闭访问时间更新。我建议把LastWriteTime作为默认判定依据。它表示文件内容最后一次被修改的时间对于日志、导出文件、临时文件这类“写一次就放着”的文件来说这个时间基本能准确反映它的实际年龄。比如一个日志文件最后一行写于 45 天前那它有极大可能在 45 天里都没被再用过删掉风险很小。如果你处理的文件是“固定名称、内容持续追加”的类型比如某个服务反复写入同一个日志文件那LastWriteTime会一直刷新只要文件还在活跃写入它就不会被误删。这也是我优先推荐它的原因。2.2 递归、空目录、占用文件与只读属性边界条件清单规则设计不能只有“过期天数”这一条。我整理了一个边界条件清单写代码前最好一条条确认下来是否递归子目录日志目录常常按年/月/日建子目录不递归的话只能清根目录效果很差。默认建议递归。是否删除空目录文件删完后按日期命名的空目录会残留时间久了也会很乱。可以选择把空目录一并删除但千万别把根目录删了。文件是否被占用正在被进程打开的日志文件删除时会抛出IOException。这种情况不能硬删只能记录错误并跳过等下次任务再处理。只读文件怎么办只读属性会导致删除失败。要不要强制删取决于你对自己的目录有多了解。稳妥做法是默认不强制把失败记录下来人工处理。时间边界是“超过 30 天”还是“满 30 天”如果某个文件的最后修改时间是 30 天前这一刻程序要不要删如果你用“超过 30 天才删”当天是安全的如果你用“满 30 天就删”边界当天也会删掉。我习惯采用前者更保守。这些看起来都是细节但漏掉任何一个上线后都可能变成事故。尤其是递归目录时遇到无权限子目录处理不好的话整个枚举过程直接崩溃后面的文件一个都清不掉。2.3 测试环境里的“时间造假”怎么做实际验证时需要人为制造一些“老文件”。我不建议去翻系统文件做测试正确做法是自己在临时目录里创建一批文件并把它们的LastWriteTime改成指定时间。用 PowerShell 就能快速完成$dir D:\CleanerTest New-Item -ItemType Directory -Force -Path $dir | Out-Null # 30天前的文件 $file30 Join-Path $dir file_30days.log New-Item -ItemType File -Path $file30 -Force | Out-Null (Get-Item $file30).LastWriteTime (Get-Date).AddDays(-30) # 31天前的文件 $file31 Join-Path $dir file_31days.log New-Item -ItemType File -Path $file31 -Force | Out-Null (Get-Item $file31).LastWriteTime (Get-Date).AddDays(-31) # 29天前的文件 $file29 Join-Path $dir file_29days.log New-Item -ItemType File -Path $file29 -Force | Out-Null (Get-Item $file29).LastWriteTime (Get-Date).AddDays(-29)有了这批已知日期的文件后面无论做 dry-run 还是正式删除验证结果都能一眼判断对不对。3. 核心实现用 C# 写一个可复用的 FileCleaner3.1 类的基本骨架清理结果对象与主流程我不喜欢写那种“一次性脚本”所以第一步就把清理逻辑封装成一个静态类FileCleaner再定义一个CleanResult来承载删除结果。这样无论以后是做成控制台工具、Windows 服务还是嵌进现有项目都能直接调用。下面是完整的类代码包含 dry-run 模式、异常记录和可选删空目录using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace FileCleanupTool { public class CleanResult { public int DeletedCount { get; set; } public int FailedCount { get; set; } public Liststring DryRunMatches { get; } new Liststring(); public Liststring Errors { get; } new Liststring(); } public static class FileCleaner { public static CleanResult Clean( string targetDirectory, int retentionDays 30, bool includeSubDirectories true, bool dryRun false) { if (!Directory.Exists(targetDirectory)) throw new DirectoryNotFoundException($目录不存在: {targetDirectory}); // 超过这个时间点的文件都算“过期” DateTime cutoffLocal DateTime.Now.AddDays(-retentionDays); var result new CleanResult(); // 1. 一次性把目录列表固定下来避免多次遍历时目录发生变化 Liststring dirs (includeSubDirectories ? GetAccessibleDirectories(targetDirectory) : new[] { targetDirectory }) .ToList(); // 2. 先删文件 foreach (string dir in dirs) { IEnumerableFileInfo files; try { files new DirectoryInfo(dir).EnumerateFiles(); } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { result.Errors.Add(${dir} 枚举失败: {ex.Message}); continue; } foreach (FileInfo file in files) { // 最后写入时间比 cutoff 晚或等于 cutoff说明没有超过保留期 if (file.LastWriteTime cutoffLocal) continue; if (dryRun) { result.DryRunMatches.Add(file.FullName); continue; } try { File.Delete(file.FullName); result.DeletedCount; } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { result.FailedCount; result.Errors.Add(${file.FullName} 删除失败: {ex.Message}); } } } // 3. 可选删掉已经变空的子目录注意保留根目录 if (!dryRun includeSubDirectories) { foreach (string dir in dirs.AsEnumerable().Reverse()) { if (string.Equals(dir, targetDirectory, StringComparison.OrdinalIgnoreCase)) continue; try { if (!Directory.EnumerateFileSystemEntries(dir).Any()) Directory.Delete(dir); } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { result.Errors.Add(${dir} 目录删除失败: {ex.Message}); } } } return result; } // 递归枚举所有子目录遇到无权限目录直接跳过不让整个流程崩溃 private static IEnumerablestring GetAccessibleDirectories(string root) { var pending new Stackstring(); pending.Push(root); while (pending.Count 0) { string current pending.Pop(); yield return current; string[] children; try { children Directory.GetDirectories(current); } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { continue; } // 入栈顺序影响遍历顺序这里反过来是为了保持先父后子的直观顺序 for (int i children.Length - 1; i 0; i--) pending.Push(children[i]); } } } }这段代码有几个地方我特意做了设计。先说第一点目录列表在一开始就转成了Liststring而不是让IEnumerablestring惰性求值。因为后面既要遍历目录删文件又要逆序遍历删空目录如果惰性求值第二次枚举可能遇到目录已被前一步删除的情况容易出一些奇奇怪怪的异常。第二点是异常过滤器的写法catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)。这样既能接住文件占用导致的删除失败又能接住权限问题同时不会把更严重的ArgumentException之类错误吞掉。第三点是递归枚举目录时用了栈而非递归函数。日志目录动辄几千个嵌套子目录如果用系统递归容易把调用栈压爆而StackT的迭代方式很克制内存占用也可控。3.2 为什么文件时间比较用而不是代码里有一个非常容易被忽略的边界判断if (file.LastWriteTime cutoffLocal) continue;cutoffLocal是DateTime.Now.AddDays(-retentionDays)。如果保留期是 30 天cutoff 就是“30 天前的这一刻”。LastWriteTime cutoff表示文件最后修改时间既可能比 cutoff 新也可能正好等于 cutoff这两种情况都会被保留。换句话说这套规则对应的是“超过 30 天就删还没超过 30 天就留”。当你把retentionDays设成 30某个文件的修改时间是 30 天前的同一分钟它不会被删等到下一分钟它就严格大于 30 天了会被删。如果你希望“满 30 天就删”只把这一行改成if (file.LastWriteTime cutoffLocal) continue;即可。我习惯用前者因为多留一个边界不会损失什么而少删一个刚满期限的文件往往更安全。3.3 删除空目录的顺序为什么要逆序文件删完后如果目录里空了我们要清理空目录。这时必须先删最深的子目录再删上一级目录否则先删父目录会导致子目录路径失效或者抛异常。所以代码里用了dirs.AsEnumerable().Reverse()。但这里有个前提dirs是Liststring顺序来自栈遍历。我的GetAccessibleDirectories用 Stack 实现实际返回顺序不一定严格从根到最深不过逆序遍历后通常能保证先遇到更深的目录。如果你用递归函数生成目录列表顺序更可控逆序删除也更可靠。这里我为了兼顾“不怕无权限目录”和“代码简短”牺牲了一点点顺序确定性但实测下来没有遇到目录删不掉的问题。如果你不需要删空目录直接把这个分支删掉即可不影响主流程。4. 上线前先“演戏”dry-run 模式与边界验证4.1 dry-run先看再删永远不要跳过我第一次写完这个工具后直接在真实日志目录上跑了一次结果把某个还在用的缓存文件删了。后来就学乖了所有清理类工具都必须有 dry-run 模式。它不会真正删除任何文件只把“计划要删除”的完整文件路径列出来帮你在正式执行前做人工确认。上面代码里Clean方法的dryRun参数就是干这个的。调用时传入dryRun: true会往result.DryRunMatches里塞匹配到的文件路径而不会真正执行File.Delete。实际用起来是这样var result FileCleaner.Clean( D:\Logs, retentionDays: 30, includeSubDirectories: true, dryRun: true); foreach (var filePath in result.DryRunMatches) Console.WriteLine($[计划删除] {filePath}); Console.WriteLine($共匹配 {result.DryRunMatches.Count} 个文件);我在给任何新环境部署清理器时都会先跑一轮 dry-run把输出拉出来扫一遍确认没有“意外文件”后再开正式模式。这一步看起来啰嗦但能避免绝大多数误删事故。4.2 用造出来的测试文件验证时间边界光有 dry-run 还不够还要验证边界条件。我在 2.3 节里用 PowerShell 造了三个文件29 天前、30 天前、31 天前各一个。然后把retentionDays设为 30跑 dry-run。预期结果应该是29 天前的文件保留30 天前的文件保留因为按规则正好 30 天还没超过31 天前的文件计划删除如果跑出来和预期不一致至少要反思两个问题一是时间比较的方向是不是反了二是cutoff的计算是不是被哪个时区坑了。这种测试不需要写单元测试框架直接在控制台 Main 里跑一遍即可。但如果你想把工具持续维护下去我建议把这一场景写成正式的单元测试防止以后改代码改出回归。4.3 还要验证异常场景除了时间边界我还建议测试以下几种异常场景无权限的子目录把测试目录的某个子目录的权限改为拒绝Everyone读取然后看工具会不会崩溃。正在被占用的文件用File.Open把一个目标文件锁住再跑清理确认工具不会崩而是把该文件记录到Errors列表并跳过。只读文件给文件加上只读属性确认删除失败被记录。这些场景如果你不提前测等到上线后才遇到排查起来成本会高很多。至少要把“工具不会因为单个文件失败而中断”这一条验证清楚。5. 挂到自动运行任务计划、服务集成与防重入5.1 命令行参数与控制台入口为了把清理器放到 Windows 任务计划里最好给它一个简单的命令行入口。我通常是这样写 Main 的using System; using System.IO; namespace FileCleanupTool { static class Program { static int Main(string[] args) { string directory args.Length 0 ? args[0] : Directory.GetCurrentDirectory(); int days 30; bool dryRun false; for (int i 1; i args.Length; i) { switch (args[i]) { case --days when i 1 args.Length: days int.Parse(args[i]); break; case --dryrun: dryRun true; break; case --help: Console.WriteLine(FileCleaner 目录 [--days 保留天数] [--dryrun]); return 0; } } var result FileCleaner.Clean( directory, retentionDays: days, includeSubDirectories: true, dryRun: dryRun); if (dryRun) { foreach (var f in result.DryRunMatches) Console.WriteLine($[计划删除] {f}); } Console.WriteLine($删除完成成功 {result.DeletedCount}失败 {result.FailedCount}); if (result.Errors.Count 0) { foreach (var error in result.Errors) Console.WriteLine($错误{error}); return 1; } return 0; } } }这种入口的好处是语法简单任务计划里可以直接传参。比如每天凌晨清理D:\Logs保留 30 天命令可以写成FileCleaner.exe D:\Logs --days 30想先演练一轮加上--dryrun即可。5.2 挂到 Windows 任务计划时的几个注意事项Windows 任务计划程序里新建任务时我踩过几个坑触发器时间建议选“每天”或“每周”运行时间放在凌晨低峰期不要和备份任务挤在一起。起始于可选在“操作”里如果直接写程序路径任务计划的工作目录不一定对。如果你的清理器要读相对路径务必填一个明确的起始目录。使用最高权限运行清理日志目录很可能涉及系统日志目录或其他受保护路径一般需要勾选“使用最高权限运行”。但这也意味着要谨慎测试别把不该删的删了。账户尽量给清理器一个专门的账户而不是用某个员工离离职后就被禁用的个人账户。在任务计划里加完任务后最好手动“运行”一次确保退出代码是 0。因为任务计划默认只记录程序的退出码退出码非 0 就能看到告警方便定位失败原因。5.3 防止多个实例同时清理用 Mutex 兜底任务计划偶尔会因为系统时间调整、前一天任务卡住等原因导致两个清理进程同时跑。两个进程同时操作同一个目录轻则重复删除报错重则可能有一方在枚举目录时正好目录被另一方删除引发异常。我的解决方案是在 Main 开头加一个全局Mutexusing (var mutex new Mutex(true, Global\\FileCleaner_8F3A2B1D, out bool createdNew)) { if (!createdNew) { Console.WriteLine(已有清理进程在运行本次退出); return 2; } // 正常的清理逻辑 }Global前缀表示系统全局互斥这样不同会话下也只会有一个实例在跑。如果任务计划里配了“重复任务”互斥锁可以保证同一时刻只有一个清理进程在执行另一次触发直接退出。5.4 日志留痕别让工具变成“安静的破坏者”自动清理工具最怕的就是“出了问题你不知道”。所以我强烈建议在 Main 里把结果写入日志文件。最简单的方式是追加到一个文本文件里File.AppendAllText( FileCleaner.log, $[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 成功{result.DeletedCount} 失败{result.FailedCount} 目录{directory}{Environment.NewLine}, System.Text.Encoding.UTF8);如果失败数大于 0逐条把Errors写进去。这样哪天有人问“我的文件怎么没了”你可以直接翻日志快速定位到具体删除时间。没有日志的清理工具就像没有黑匣子的航班不建议飞。6. 上线之后我踩过的坑与最后几点建议6.1 删除失败的第一大原因文件被占用我做压力测试时故意让一个服务持续往日志目录写文件。清理器跑起来后那些刚被打开写入的日志文件果然报了IOException。文件被占用时删除会直接失败这其实是正常现象。我当时差点想用“强制删除”的方式去解决后来忍住了。正确的做法是让工具记录失败原因并跳过等下一次计划任务再来处理。当一个文件已经超过 30 天没变化它大概率不会被长期占用如果它老是被占用那它可能是正在活跃使用的文件更不该被强行删掉。后来我在服务里接了一个“最后写入时间”检查如果文件最近 5 分钟还有写入即使已超过保留期也额外跳过。这能避免在高频写入场景下误删“暂时没来得及刷新时间”的文件算是一道额外的保险。6.2 权限不足和只读属性怎么处理权限问题主要体现在两个地方一是目录枚举阶段Directory.GetDirectories遇到无权限子目录会抛UnauthorizedAccessException二是文件删除阶段文件有只读属性时也会失败。我的处理思路是“不硬闯”。目录枚举阶段跳过无权限子目录把失败记录到Errors文件删除阶段也只记录错误。如果你确认某个目录必须清理更稳妥的做法是把“运行权限”提上去而不是在代码里强行改文件属性。有朋友问过“可不可以先File.SetAttributes(file.FullName, FileAttributes.Normal)把只读拿掉再删”技术上可行但我不推荐默认开启。因为你可能为了清理一个垃圾文件顺便把一个用户有意设置为只读的正式文件删掉了。如果真要加这个能力至少用参数控制并且日志里要记录“强制清除只读”的行为。6.3 网络目录、时区与时间戳失真如果你的指定目录是网络共享路径比如\\nas\share\logs清理器会面临网络延迟和不稳定问题。枚举大量文件可能很慢中途还可能因为网络闪断抛异常。我建议控制任务频率并且每次运行前先检查路径可达性如果不可达直接记录日志退出不要硬试。时区问题虽然不太常见但值得提醒。上面代码用的DateTime.Now和FileInfo.LastWriteTime都是本地时间。如果机器时区被改动或者程序部署在跨时区的服务器上最好改成使用 UTC 时间比较。把cutoffLocal改成DateTime.UtcNow.AddDays(-retentionDays)把file.LastWriteTime改成file.LastWriteTimeUtc逻辑会更统一。时间戳失真也很隐蔽。比如文件从备份恢复后LastWriteTime可能被还原成备份时间看起来“很旧”但实际上它刚恢复出来可能还需要使用。对于极端情况可以在文件名里维护“业务日期”比如log-20250101.txt优先按文件名日期判断LastWriteTime作为兜底。当然这要看业务是否允许。6.4 我最后的几点使用建议这个清理工具看起来很简单真正落地后我最大的体会是规则比代码重要。代码写错了很容易发现规则定错了往往会以“误删”的方式在深夜给你惊喜。所以每次新增一种文件类型我都会先跑 dry-run再看看日志最后才放心交给任务计划。另外清理任务一定不要做成“只删文件什么都不管”。至少要把失败项暴露出来。我自己的阈值是如果一次运行失败超过 10 个文件就给邮箱发告警。因为这说明系统可能存在更严重的问题而不是单纯某个文件被占用。如果以后需求升级比如要“按文件大小”“按文件扩展名”“按正则匹配文件名”组合清理这套FileCleaner的骨架只要在foreach (FileInfo file in files)处加过滤条件就能扩展。我已经在一个内部工具里加了“只删除超过 30 天且大小大于 100MB 的临时文件”改动量大概只有十行。最后分享一个小技巧正式部署前在目录里放一个永久保留的占位文件比如.keep然后在清理规则里主动排除.keep。这样哪怕某天递归逻辑写错至少这个占位文件还在能帮你定位“目录是不是被整个端掉了”。拿我自己来说这个工具上线快两年已经删掉了上百万个日志和临时文件最值钱的不是那几百行代码而是先想清楚边界、做好 dry-run 和异常记录这套完整思路。

相关推荐

Claude Code 扩展机制(二):从 Session 启动到一次响应,完整执行流走一遍
Claude Code 扩展机制(二):从 Session 启动到一次响应,完整执行流走一遍

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 14:10:55

Matlab工程化实战:从OOP图像处理到Simulink联合仿真的高频问题解析
Matlab工程化实战:从OOP图像处理到Simulink联合仿真的高频问题解析

从“Matlab学习记录30”这个标题就能看出来,这显然是一个长期使用者的阶段性整理。能写到第30篇,说明不是三天热度的新手,而是真正把Matlab当生产工具在用的人。这篇记录我会围绕最近极高频出现的几个方向来梳理:图像处理系统的OO… · 2026/9/26 14:10:55

智源 ArXiv CLI 开源实战:2亿+论文如何接入 TaoToken 成为科研智能体技能包
智源 ArXiv CLI 开源实战:2亿+论文如何接入 TaoToken 成为科研智能体技能包

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 14:10:55

Atlas 300V 24G部署YOLO完整指南:从环境配置到推理优化
Atlas 300V 24G部署YOLO完整指南:从环境配置到推理优化

上周一个做安防的朋友突然问我:Atlas 300V 24G到底是运算加速卡吗?接着又发来一句——我刚拿它在上面部署YOLO,部署到怀疑人生。这两句话我太熟了。过去大半年我一直在一台装着两张Atlas 300V 24G的服务器上做目标检测推理,从完全… · 2026/9/26 14:53:13

开源代码审查协议:CLI驱动的Git Diff+LLM结构化审查
开源代码审查协议:CLI驱动的Git Diff+LLM结构化审查

1. 这不是另一个“AI代码助手”,而是一套可审计、可复现、可嵌入CI的开源代码审查协议你有没有遇到过这样的场景:团队里新来一个实习生,提交了PR,你点开GitHub页面,盯着diff看了三分钟,心里嘀咕“这行逻辑好… · 2026/9/26 14:53:13

VirtualBox 2026 开发者虚拟机搭建全攻略:避坑与性能调优
VirtualBox 2026 开发者虚拟机搭建全攻略:避坑与性能调优

1. 为什么2026年还要折腾本地虚拟机先把结论放前面:如果你是一名开发者,尤其是做后端、运维、嵌入式、安全测试或者需要频繁切换操作系统环境的人,本地虚拟机依然是性价比最高的方案之一。云主机虽然方便,但延迟、网络依赖、按量计… · 2026/9/26 14:53:13

Zotero集成腾讯翻译API完整指南
Zotero集成腾讯翻译API完整指南

1. 项目概述:为什么要在Zotero里集成腾讯翻译API? Zotero PDF翻译这件事,我从2021年就开始折腾,最早用的是Google Translate的网页抓取方案,后来试过DeepL的本地代理、有道词典的OCR直连,再到去年开始大规… · 2026/9/26 14:53:13

Qt中SQLiteCipher加密库操作:多连接与跨库查询实战
Qt中SQLiteCipher加密库操作:多连接与跨库查询实战

简介:面向Qt开发者的SQLite加密与多库操作实例包,聚焦SqliteCipher提供的AES-256文件级加密,覆盖QSQLITE_CIPHER驱动配置、密钥设置、多数据库连接管理,以及基于ATTACH DATABASE的跨库联合查询等典型场景,适合需要安全… · 2026/9/26 14:53:00

开源可审计的AI代码评审新范式:Agent驱动的open-code-review
开源可审计的AI代码评审新范式:Agent驱动的open-code-review

1. 项目概述:这不是一个工具,而是一套可落地的开源代码评审新范式 “open-code-review”这个词乍看像某个 GitHub 仓库名,但实际它代表的是一场正在 quietly 发生的工程实践变革——把过去依赖人工、集中在 PR 阶段、以“找 Bug”为唯一目标的… · 2026/9/26 14:53:00

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码