// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
///
/// 文件帮助类
///
public static class FileHelper
{
#region 文件操作
///
/// 读取文件内容到字符串
///
/// 要读取的文件路径
/// 文件内容为字符串
public static string ReadAllText(string filePath)
{
return File.ReadAllText(filePath);
}
///
/// 打开一个文本文件,读取文件的所有行,然后关闭文件
///
/// 要打开以进行读取的文件路径
/// 包含文件所有行的字符串
public static async Task ReadAllTextAsync(string filePath)
{
using var reader = File.OpenText(filePath);
return await reader.ReadToEndAsync();
}
///
/// 打开一个文本文件,读取文件的所有字节,然后关闭文件
///
/// 要打开以进行读取的文件路径
/// 包含文件所有字节的字节数组
public static async Task ReadAllBytesAsync(string filePath)
{
await using var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
var result = new byte[stream.Length];
_ = await stream.ReadAsync(result.AsMemory(0, (int)stream.Length));
return result;
}
///
/// 打开一个文本文件,读取文件的所有行,然后关闭文件
///
/// 要打开以进行读取的文件
/// 文件的编码默认为 UTF8
/// 指定操作系统应如何打开文件默认为 Open
/// 定义对文件的读取、写入或读写访问的常量默认为 Read
/// 包含控制其他 FileStream 对象可以对同一文件拥有的访问类型的常量默认为 Read
/// StreamReader 缓冲区的长度默认为 4096
/// 指示 FileStream 选项默认为 Asynchronous(文件将用于异步读取)和 SequentialScan(文件将从开始到末尾顺序访问)
/// 包含文件所有行的字符串数组
public static async Task ReadAllLinesAsync(string path,
Encoding? encoding = null,
FileMode fileMode = FileMode.Open,
FileAccess fileAccess = FileAccess.Read,
FileShare fileShare = FileShare.Read,
int bufferSize = 4096,
FileOptions fileOptions = FileOptions.Asynchronous | FileOptions.SequentialScan)
{
encoding ??= Encoding.UTF8;
List lines = [];
await using (FileStream stream = new(path, fileMode, fileAccess, fileShare, bufferSize, fileOptions))
{
using StreamReader reader = new(stream, encoding);
while (await reader.ReadLineAsync() is { } line)
{
lines.Add(line);
}
}
return [.. lines];
}
///
/// 打开一个文本文件,读取不包含 BOM 的内容
///
/// 要打开以进行读取的文件
/// 包含文件所有行的字符串
public static async Task ReadWithoutBomAsync(string path)
{
var content = await ReadAllBytesAsync(path);
return ConvertFromBytesWithoutBom(content)!;
}
///
/// 将字节数组 byte[]转换为不包含字节顺序标记(BOM)的字符串
///
/// 要转换为字符串的 byte[]数组
/// 获取字符串的编码默认为 UTF8
/// 转换得到的字符串
private static string? ConvertFromBytesWithoutBom(byte[]? bytes, Encoding? encoding = null)
{
if (bytes is null)
{
return null;
}
encoding ??= Encoding.UTF8;
var hasBom = bytes is [0xEF, 0xBB, 0xBF, ..];
return hasBom ? encoding.GetString(bytes, 3, bytes.Length - 3) : encoding.GetString(bytes);
}
///
/// 将文本内容写入到文件
///
/// 要写入的文件路径
/// 要写入的文本内容
public static void WriteAllText(string filePath, string content)
{
File.WriteAllText(filePath, content);
}
///
/// 将文本内容追加到文件
///
/// 要追加的文件路径
/// 要追加的文本内容
public static void AppendAllText(string filePath, string content)
{
File.AppendAllText(filePath, content);
}
///
/// 创建文件,如果文件不存在
///
/// 文件路径
public static void CreateIfNotExists(string filePath)
{
if (!File.Exists(filePath))
{
_ = File.Create(filePath);
}
}
///
/// 删除一个文件,如果文件存在
///
/// 要删除的文件路径
public static void DeleteIfExists(string filePath)
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
///
/// 移动文件到另一个位置
///
/// 当前文件的路径
/// 目标文件的路径
public static void Move(string sourcePath, string destinationPath)
{
File.Move(sourcePath, destinationPath);
}
///
/// 复制文件到另一个位置
///
/// 当前文件的路径
/// 目标文件的路径
/// 如果目标位置已经存在同名文件,是否覆盖
public static void Copy(string sourcePath, string destinationPath, bool overwrite = false)
{
File.Copy(sourcePath, destinationPath, overwrite);
}
///
/// 清空文件内容
///
/// 文件的绝对路径
public static void Clean(string filePath)
{
if (!File.Exists(filePath))
{
return;
}
// 删除文件
File.Delete(filePath);
// 重新创建该文件
_ = File.Create(filePath);
}
#endregion 文件操作
#region 文件信息
///
/// 获取文件的哈希值
///
/// 要计算哈希值的文件路径
/// 文件的哈希值
public static string GetHash(string filePath)
{
using var stream = File.OpenRead(filePath);
return HashHelper.StreamMd5(stream);
}
///
/// 获取指定文件大小
///
///
///
public static long GetSize(string filePath)
{
return new FileInfo(filePath).Length;
}
///
/// 从文件的绝对路径中获取文件名(包含扩展方法名)
///
///
///
public static string GetName(string filePath)
{
return Path.GetFileName(filePath);
}
///
/// 获取随机文件名
///
///
public static string GetRandomName()
{
return Path.GetRandomFileName();
}
///
/// 根据时间得到文件名
/// yyyyMMddHHmmssfff
///
///
public static string GetDateName()
{
return DateTime.Now.ToString("yyyyMMddHHmmssfff");
}
///
/// 从文件的绝对路径中获取扩展方法名
/// 文件扩展方法名是包含点(.)的
///
///
///
public static string GetExtension(string filePath)
{
return Path.GetExtension(filePath);
}
///
/// 从文件的绝对路径中获取文件名(不包含扩展方法名)
///
///
///
public static string GetNameWithoutExtension(string filePath)
{
return Path.GetFileNameWithoutExtension(filePath);
}
///
/// 生成唯一的文件名,上传文件使用
///
/// 包含扩展方法名的源文件名
///
public static string GetUniqueName(string fileName)
{
var fileNameWithoutExtension = GetNameWithoutExtension(fileName);
var fileExtension = GetExtension(fileName);
var uniqueFileName = $"{fileNameWithoutExtension}_{GetDateName()}_{GetRandomName()}";
return uniqueFileName + fileExtension;
}
///
/// 获取文本文件的行数
///
/// 文件的绝对路径
///
public static int GetTextLineCount(string filePath)
{
// 将文本文件的各行读到一个字符串数组中
var rows = File.ReadAllLines(filePath);
// 返回行数
return rows.Length;
}
#endregion 文件信息
#region 文件检查
///
/// 检查文件是否存在
///
/// 要检查的文件路径
/// 如果文件存在返回 true,否则返回 false
public static bool Exists(string filePath)
{
return File.Exists(filePath);
}
///
/// 检查文件是否被锁定
///
/// 要检查的文件路径
/// true 如果文件没有被锁定,可以进行读写操作,否则 false
public static bool IsUnlocked(string filePath)
{
try
{
using var fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
// 如果没有异常,文件没有被锁定
return true;
}
catch (IOException)
{
// 如果发生异常,文件可能被锁定
return false;
}
}
#endregion 文件检查
}