为什么直接用 System.IO
不够用
因为
File和
Directory静态类虽然功能全,但每做一件事都要手动判空、捕获异常、检查路径合法性。比如
File.Exists(path)返回
false,你没法立刻知道是文件不存在,还是权限不足,或是路径含非法字符。真实业务里,一个“保存配置”操作常要:确保目录存在、创建缺失父目录、原子写入、失败时清理临时文件——这些逻辑反复出现,不封装就会散落在各处。
FileHelper
应该只暴露哪些核心方法
聚焦高频、易出错、有共性处理的场景,不是把
System.IO全部重包一层。推荐这四个入口:
WriteAllText(string path, string content, Encoding? encoding = null):自动创建父目录,抛出带上下文的异常(如“无法创建目录 D:\a\b\c”)
ReadAllText(string path, Encoding? encoding = null):统一处理
FileNotFoundException和
UnauthorizedAccessException,转为更明确的业务异常
Copy(string source, string dest, bool overwrite = false):内部调用
File.Copy,但先校验源文件可读、目标目录可写,并支持取消令牌
GetFiles(string directory, string pattern = "*.*", SearchOption option = SearchOption.TopDirectoryOnly):返回
IEnumerable<string></string>而非数组,避免大目录一次性加载内存
路径安全和编码问题怎么兜底
用户传进来的
path很可能含
..、空格、Unicode 控制符,或默认用系统编码读中文内容却在 Linux 上运行。必须在入口就拦截: 用
Path.GetFullPath(path)归一化路径,再用
Path.IsPathRooted()+ 检查是否以
Path.GetPathRoot()开头,防路径穿越 对所有
path参数做
string.IsNullOrWhiteSpace()和
Path.GetInvalidPathChars()扫描,发现非法字符立即抛
ArgumentException
ReadAllText/
WriteAllText默认用
Encoding.UTF8,不依赖
Encoding.Default—— 后者在中文 Windows 是 GB2312,在 Docker 容器里可能是 ASCII
异步支持要不要加?加到什么程度
加,但只加真正阻塞 I/O 的方法,比如
ReadAllTextAsync和
WriteAllTextAsync。别为了“看起来现代”而给
Exists或
Delete加
Async后缀——它们底层是元数据查询,同步调用开销极小,强行异步反而增加调度成本。
关键点:
异步方法内部用File.ReadAllTextAsync/
File.WriteAllTextAsync,不自己开线程池 所有异步方法签名必须接受
CancellationToken,且在打开文件前就检查是否已取消 不要提供“同步转异步”的包装器(如
Task.Run(() => ReadAllText(...))),这是反模式
真正难处理的是长路径(>260 字符)和符号链接循环——这些得靠调用方自己控制输入,帮助类最多在文档里标红提醒,硬拦会破坏灵活性。
