文件工具类-FileUtil
# 简介
在IO操作中,文件的操作相对来说是比较复杂的,但也是使用频率最高的部分,我们几乎所有的项目中几乎都躺着一个叫做FileUtil或者FileUtils的工具类,我想EasyTool应该将这个工具类纳入其中,解决用来解决大部分的文件操作问题。
总体来说,FileUtil类包含以下几类操作工具:
- 文件操作:包括文件目录的新建、删除、复制、移动、改名等
- 文件判断:判断文件或目录是否非空,是否为目录,是否为文件等等。
- 绝对路径:针对ClassPath中的文件转换为绝对路径文件。
- 文件名:主文件名,扩展名的获取
- 读操作:包括类似IoUtil中的getReader、readXXX操作
- 写操作:包括getWriter和writeXXX操作
在FileUtil中,我努力将方法名与Linux相一致,例如创建文件的方法并不是createFile,而是touch
,这种统一对于熟悉Linux的人来说,大大提高了上手速度。当然,如果你不熟悉Linux,那FileUtil工具类的使用则是在帮助你学习Linux命令。这些类Linux命令的方法包括:
ls
列出目录和文件touch
创建文件,如果父目录不存在也自动创建mkdir
创建目录,会递归创建每层目录del
删除文件或目录(递归删除,不判断是否为空),这个方法相当于Linux的delete命令copy
拷贝文件或目录
这些方法提供了人性化的操作,例如touch
方法,在创建文件的情况下会自动创建上层目录(我想对于使用者来说这也是大部分情况下的需求),同样mkdir
也会创建父目录。
注意
需要注意的是,del
方法会删除目录而不判断其是否为空,这一方面方便了使用,另一方面也可能造成一些预想不到的后果(比如拼写错路径而删除不应该删除的目录),所以请谨慎使用此方法。
# EasyTool.FileUtil 类
静态工具类 FileUtil,提供了类似 Linux 中文件操作命令的功能,包括:
- 拷贝文件:
Cp
- 移动文件或重命名文件:
Mv
- 删除文件:
Rm
- 创建目录:
Mkdir
- 删除目录:
Rmdir
- 列出目录内容:
Ls
# CleanInvalid-清除文件名中的在Windows下不支持的非法字符
/// <summary>
/// 清除文件名中的在Windows下不支持的非法字符,包括: \ / : * ? " < > |
/// </summary>
/// <param name="fileName">文件名(必须不包括路径,否则路径符将被替换)</param>
/// <returns>清理后的文件名</returns>
public static string CleanInvalid(string fileName)
# ContainsInvalid-文件名中是否包含在Windows下不支持的非法字符
/// <summary>
/// 文件名中是否包含在Windows下不支持的非法字符,包括: \ / : * ? " < > |
/// </summary>
/// <param name="fileName">文件名(必须不包括路径,否则路径符将被替换)</param>
/// <returns>是否包含非法字符</returns>
public static bool ContainsInvalid(string fileName)
# GetMimeType-根据文件扩展名获得MimeType
/// <summary>
/// 根据文件扩展名获得MimeType
/// </summary>
/// <param name="filePath">文件路径或文件名</param>
/// <returns>MimeType</returns>
public static string GetMimeType(string filePath)
# IsWindows-判断当前操作系统是否为 Windows
/// <summary>
/// 判断当前操作系统是否为 Windows
/// </summary>
public static bool IsWindows()
# IsUnix-判断当前操作系统是否为 Unix
/// <summary>
/// 判断当前操作系统是否为 Unix
/// </summary>
public static bool IsUnix()
# IsXbox-判断当前操作系统是否为 Xbox
/// <summary>
/// 判断当前操作系统是否为 Xbox
/// </summary>
public static bool IsXbox()
# IsMacOSX-判断当前操作系统是否为 macOS
/// <summary>
/// 判断当前操作系统是否为 macOS
/// </summary>
public static bool IsMacOSX()
# IsEmpty-判断文件或目录是否为空
/// <summary>
/// 判断文件或目录是否为空
///
/// 目录:里面没有文件时为空
/// 文件:文件大小为0时为空
/// </summary>
/// <param name="path">文件或目录的路径</param>
/// <returns>是否为空</returns>
public static bool IsEmpty(string path)
# LoopFiles-递归遍历目录以及子目录中的所有文件
/// <summary>
/// 递归遍历目录以及子目录中的所有文件
/// </summary>
/// <param name="path">要遍历的目录路径</param>
/// <param name="searchPattern">文件过滤规则,例如 "*.txt",默认为 "*"</param>
/// <returns>所有符合过滤规则的文件完整路径的列表</returns>
public static List<string> LoopFiles(string path, string searchPattern = "*")
/// <summary>
/// 递归遍历目录以及子目录中的所有文件
/// </summary>
/// <param name="path">要遍历的目录路径</param>
/// <param name="maxDepth">遍历的最大深度,-1 表示遍历到没有目录为止</param>
/// <param name="searchPattern">文件过滤规则,例如 "*.txt",默认为 "*"</param>
/// <returns>所有符合过滤规则的文件完整路径的列表</returns>
public static List<string> LoopFiles(string path, int maxDepth = -1, string searchPattern = "*")
# Clean-清空文件夹
/// <summary>
/// 清空文件夹
/// 注意:清空文件夹时不会判断文件夹是否为空,如果不空则递归删除子文件或文件夹
/// </summary>
/// <param name="dirPath">文件夹路径</param>
/// <returns>是否成功清空文件夹</returns>
public static bool Clean(string dirPath)
# CleanEmpty-清理空文件夹
/// <summary>
/// 清理空文件夹
/// 此方法用于递归删除空的文件夹,不删除文件
/// 如果传入的文件夹本身就是空的,删除这个文件夹
/// </summary>
/// <param name="dirPath">文件夹路径</param>
/// <returns>是否成功清理空文件夹</returns>
public static bool CleanEmpty(string dirPath)
# CreateTempFile-在默认临时文件目录下创建临时文件
/// <summary>
/// 在默认临时文件目录下创建临时文件
/// </summary>
/// <returns>临时文件全路径</returns>
public static string CreateTempFile()
# Ls-列出指定路径下的目录和文件
/// <summary>
/// 列出指定路径下的目录和文件
/// </summary>
/// <param name="path">目录绝对路径或者相对路径</param>
/// <returns>文件列表(包含目录)</returns>
public static List<string> Ls(string path)
# Touch-创建文件及其父目录
/// <summary>
/// 创建文件及其父目录
///
/// 如果这个文件存在,直接返回这个文件
/// </summary>
/// <param name="path">文件绝对路径或者相对路径</param>
/// <returns>创建或者获取到的文件对象</returns>
public static FileInfo Touch(string path)
# Cp-拷贝文件
/// <summary>
/// 拷贝文件
/// </summary>
/// <param name="src">源文件路径</param>
/// <param name="destinationPath">目标文件路径</param>
public static void Cp(string src, string dest)
# Copy-复制文件或目录
/// <summary>
/// 复制文件或目录
///
/// 描述:
/// 1、src和dest都为目录,则将src目录及其目录下所有文件目录拷贝到dest下
/// 2、src和dest都为文件,直接复制,名字为dest
/// 3、src为文件,dest为目录,将src拷贝到dest目录下
/// </summary>
/// <param name="src">源文件或目录</param>
/// <param name="dest">目标文件或目录,目标不存在会自动创建(目录、文件都创建)</param>
/// <param name="isOverride">是否覆盖</param>
/// <returns>是否成功复制</returns>
public static bool Copy(string src, string dest, bool isOverride)
# Mv-移动文件或重命名文件
/// <summary>
/// 移动文件或重命名文件
/// </summary>
/// <param name="src">源文件路径</param>
/// <param name="dest">目标文件路径</param>
public static void Mv(string src, string dest)
# Move-移动文件或者目录
/// <summary>
/// 移动文件或者目录
/// </summary>
/// <param name="src">源文件或者目录</param>
/// <param name="dest">目标文件或者目录</param>
/// <param name="isOverride">是否覆盖目标,只有目标为文件才覆盖</param>
/// <returns></returns>
public static bool Move(string src, string dest, bool isOverride)
# Rename-修改文件或目录的文件名
/// <summary>
/// 修改文件或目录的文件名,不变更路径,只是简单修改文件名
///
/// 说明:
/// 1、isRetainExt为true时,保留原扩展名。如 FileUtil.Rename(file, "aaa", true, false) xx/xx.png =》xx/aaa.png
/// 2、isRetainExt为false时,不保留原扩展名,需要在newName中说明扩展名。如 FileUtil.Rename(file, "aaa.jpg", false, false) xx/xx.png =》xx/aaa.jpg
/// </summary>
/// <param name="file">被修改的文件</param>
/// <param name="newName">新的文件名</param>
/// <param name="isRetainExt">是否保留原文件的扩展名,如果保留,则newName不需要加扩展名</param>
/// <param name="isOverride">是否覆盖目标文件</param>
/// <returns>目标文件</returns>
/// <summary>
/// 修改文件或目录的文件名,不变更路径,只是简单修改文件名
///
/// 说明:
/// 1、isRetainExt为true时,保留原扩展名。如 FileUtil.Rename(file, "aaa", true, false) xx/xx.png =》xx/aaa.png
/// 2、isRetainExt为false时,不保留原扩展名,需要在newName中说明扩展名。如 FileUtil.Rename(file, "aaa.jpg", false, false) xx/xx.png =》xx/aaa.jpg
/// </summary>
/// <param name="file">被修改的文件</param>
/// <param name="newName">新的文件名</param>
/// <param name="isRetainExt">是否保留原文件的扩展名,如果保留,则newName不需要加扩展名</param>
/// <param name="isOverride">是否覆盖目标文件</param>
/// <returns>目标文件</returns>
public static FileInfo Rename(FileInfo file, string newName, bool isRetainExt, bool isOverride)
# GetAbsolutePath-获取绝对路径
/// <summary>
/// 获取绝对路径
/// </summary>
/// <param name="path">相对路径</param>
/// <returns>绝对路径</returns>
public static string GetAbsolutePath(string path)
# IsAbsolutePath-判断给定路径是否是绝对路径
/// <summary>
/// 判断给定路径是否是绝对路径
/// </summary>
/// <param name="path">给定路径</param>
/// <returns>是否是绝对路径</returns>
public static bool IsAbsolutePath(string path)
# IsDirectory-判断是否为目录
/// <summary>
/// 判断是否为目录,如果 path 为 null,则返回 false
/// </summary>
/// <param name="path">给定路径</param>
/// <returns>是否为目录</returns>
public static bool IsDirectory(string path)
# IsFile-判断是否为文件
/// <summary>
/// 判断是否为文件,如果 path 为 null,则返回 false
/// </summary>
/// <param name="path">给定路径</param>
/// <returns>是否为文件</returns>
public static bool IsFile(string path)
# Equals-比较两个文件内容是否相同
/// <summary>
/// 比较两个文件内容是否相同
///
/// 首先比较长度,长度一致再比较内容,比较内容采用按行读取,每行比较
/// </summary>
/// <param name="file1">文件1</param>
/// <param name="file2">文件2</param>
/// <returns>是否相同</returns>
public static bool Equals(FileInfo file1, FileInfo file2)
# Normalize-修复路径
/// <summary>
/// 修复路径
///
/// 如果原路径尾部有分隔符,则保留为标准分隔符(/),否则不保留
///
/// 说明:
/// 1. 统一用 /
/// 2. 多个 / 转换为一个 /
/// 3. 去除左边空格
/// 4. .. 和.转换为绝对路径,当..多于已有路径时,直接返回根路径
///
/// 示例:
/// "/foo//" =》 "/foo/"
/// "/foo/./" =》 "/foo/"
/// "/foo/../bar" =》 "/bar"
/// "/foo/../bar/" =》 "/bar/"
/// "/foo/../bar/../baz" =》 "/baz"
/// "foo/bar/.." =》 "foo"
/// "foo/../bar" =》 "bar"
/// "foo/../../bar" =》 "bar"
/// </summary>
/// <param name="path">原路径</param>
/// <returns>修复后的路径</returns>
public static string Normalize(string path)
# SubPath-获得相对子路径
/// <summary>
/// 获得相对子路径,忽略大小写
///
/// 示例:
/// dirPath: d:/aaa/bbb filePath: d:/aaa/bbb/ccc =》 ccc
/// dirPath: d:/Aaa/bbb filePath: d:/aaa/bbb/ccc.txt =》 ccc.txt
/// dirPath: d:/Aaa/bbb filePath: d:/aaa/bbb/ =》 ""
/// </summary>
/// <param name="dirPath">绝对父路径</param>
/// <param name="filePath">文件路径</param>
/// <returns>相对子路径</returns>
public static string SubPath(string dirPath, string filePath)
# Rm-删除文件
/// <summary>
/// 删除文件
/// </summary>
/// <param name="path">文件路径</param>
public static void Rm(string path)
# Mkdir-创建目录
/// <summary>
/// 创建目录
/// </summary>
/// <param name="path">目录路径</param>
public static void Mkdir(string path)
# Rmdir-删除目录
/// <summary>
/// 删除目录
/// </summary>
/// <param name="path">目录路径</param>
public static void Rmdir(string path)
# GetFileName-获取文件名
/// <summary>
/// 获取文件名
/// </summary>
/// <param name="file">文件</param>
/// <returns>文件名</returns>
public static string GetFileName(FileInfo file)
/// <summary>
/// 获取文件名
/// </summary>
/// <param name="filePath">文件</param>
/// <returns>文件名</returns>
public static string GetFileName(string filePath)
# GetFileSuffix-获取后缀名,扩展名不带“.”
/// <summary>
/// 获取后缀名,扩展名不带“.”
/// </summary>
/// <param name="file">文件</param>
/// <returns>文件后缀名</returns>
public static string GetFileSuffix(FileInfo file)
/// <summary>
/// 获取后缀名,扩展名不带“.”
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>文件后缀名</returns>
public static string GetFileSuffix(string filePath)
# GetFilePrefix-获取文件名,不带扩展名
/// <summary>
/// 获取文件名,不带扩展名
/// </summary>
/// <param name="file">文件</param>
/// <returns>文件名</returns>
public static string GetFilePrefix(FileInfo file)
/// <summary>
/// 获取文件名,不带扩展名
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>文件名</returns>
public static string GetFilePrefix(string filePath)
# GetType-文件流头部信息获得文件类型
/// <summary>
/// 文件流头部信息获得文件类型
///
/// 说明:
/// 1、无法识别类型默认按照扩展名识别
/// 2、xls、doc、msi、ppt、vsd头信息无法区分,按照扩展名区分
/// 3、zip可能为docx、xlsx、pptx、jar、war头信息无法区分,按照扩展名区分
/// </summary>
/// <param name="file">文件</param>
/// <returns>类型,文件的扩展名,未找到为null</returns>
public static string GetType(FileInfo file)
# GetInputStream-获得输入流
/// <summary>
/// 获得输入流
/// </summary>
/// <param name="file">文件</param>
/// <returns>输入流</returns>
public static Stream GetInputStream(FileInfo file)
# GetOutputStream-获得输出流
/// <summary>
/// 获得一个输出流对象
/// </summary>
/// <param name="file">文件</param>
/// <returns>输出流对象</returns>
public static Stream GetOutputStream(FileInfo file)
/// <summary>
/// 获得一个输出流对象
/// </summary>
/// <param name="file">输出到的文件路径,绝对路径</param>
/// <returns>输出流对象</returns>
public static Stream GetOutputStream(string path)
# GetBOMInputStream-获得BOM输入流
/// <summary>
/// 获得BOM输入流,用于处理带BOM头的文件
/// </summary>
/// <param name="file">文件</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>BOM输入流</returns>
public static StreamReader GetBOMInputStream(FileInfo file, Encoding encoding = null)
# GetReader-获得一个文件读取流
/// <summary>
/// 获得一个文件读取流
/// </summary>
/// <param name="file">文件</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>文件读取流</returns>
public static StreamReader GetReader(FileInfo file, Encoding encoding = null)
# ReadBytes-读取文件所有数据
/// <summary>
/// 读取文件所有数据
///
/// 文件的长度不能超过int.MaxValue
/// </summary>
/// <param name="file">文件</param>
/// <returns>字节码</returns>
public static byte[] ReadBytes(FileInfo file)
/// <summary>
/// 读取文件所有数据
///
/// 文件的长度不能超过int.MaxValue
/// </summary>
/// <param name="path">文件路径</param>
/// <returns>字节码</returns>
public static byte[] ReadBytes(string path)
# ReadString-读取文件内容
/// <summary>
/// 读取文件内容
/// </summary>
/// <param name="file">文件</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>内容</returns>
public static string ReadString(FileInfo file, Encoding encoding = null)
/// <summary>
/// 读取文件内容
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>内容</returns>
public static string ReadString(string path, Encoding encoding = null)
/// <summary>
/// 读取网络文件内容
/// </summary>
/// <param name="url">网络文件地址</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>内容</returns>
public static string ReadString(Uri url, Encoding encoding = null)
# ReadAllLines-从文件中读取每一行数据
/// <summary>
/// 从文件中读取每一行数据
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns></returns>
public static string[] ReadAllLines(string path, Encoding encoding = null)
# GetLineSeparator-获取当前系统的换行分隔符
/// <summary>
/// 获取当前系统的换行分隔符
/// </summary>
/// <returns>换行分隔符</returns>
public static string GetLineSeparator()
# WriteString-将string写入文件,覆盖模式
/// <summary>
/// 将string写入文件,覆盖模式
/// </summary>
/// <param name="content">写入的内容</param>
/// <param name="path">文件路径</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>文件信息</returns>
public static FileInfo WriteString(string content, string path, Encoding encoding = null)
# AppendString-将string写入文件,追加模式
/// <summary>
/// 将string写入文件,追加模式
/// </summary>
/// <param name="content">写入的内容</param>
/// <param name="path">文件路径</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>文件信息</returns>
public static FileInfo AppendString(string content, string path, Encoding encoding = null)
# WriteLines-将列表写入文件,覆盖模式
/// <summary>
/// 将列表写入文件,覆盖模式
/// </summary>
/// <param name="list">写入的内容</param>
/// <param name="path">文件路径</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>文件信息</returns>
public static FileInfo WriteLines(List<string> list, string path, Encoding encoding = null)
# AppendLines-将列表写入文件,追加模式
/// <summary>
/// 将列表写入文件,追加模式
/// </summary>
/// <param name="list">写入的内容</param>
/// <param name="path">文件路径</param>
/// <param name="encoding">编码格式,默认为UTF-8</param>
/// <returns>文件信息</returns>
public static FileInfo AppendLines(List<string> list, string path, Encoding encoding = null)
# WriteBytes-写入数据到文件
/// <summary>
/// 写入数据到文件
/// </summary>
/// <param name="data">数据</param>
/// <param name="file">目标文件</param>
/// <param name="offset">数据开始位置</param>
/// <param name="len">数据长度</param>
/// <param name="isAppend">是否追加模式</param>
/// <returns>文件信息</returns>
public static FileInfo WriteBytes(byte[] data, FileInfo file, int offset, int len, bool isAppend)
# 参考链接
上次更新: 2023/04/26, 22:10:06