ASP.NET 8 AOT 遍历文件夹获取文件名称及时长

朋友下了N多视频

记不住文件夹下都有啥了…

问批处理怎么导出文件夹下所有文件名及视频时长…


批处理导出文件名好弄,获取视频时长真没用过…

想到 .net 控制台程序 AOT 发布,不和批处理差不多效果…


新建个控制台项目选下使用AOT

image



首先要获取文件的时长,我们需要用下 TagLibSharp

Install-Package TagLibSharp


然后是遍历文件夹,让万能的 chatgpt 写一个:


		/// <summary>
		/// 列出指定目录及其子目录中的文件,限制递归深度。
		/// </summary>
		/// <param name="path">当前目录路径</param>
		/// <param name="writer">StreamWriter 对象,用于写入文件</param>
		/// <param name="currentDepth">当前递归深度</param>
		static void ListFilesAndDirectories(string path, StreamWriter writer, int currentDepth)
		{
			// 最大递归深度设定为3
			const int maxDepth = 3;

			// 如果当前深度超过最大深度,则返回
			if (currentDepth > maxDepth)
			{
				return;
			}

			try
			{
				// 获取当前目录下的所有文件
				string[] files = Directory.GetFiles(path);
				foreach (string file in files)
				{
					if (file != outputFilePath  && file != ownFilePath)
					{
						FileInfo fileInfo = new FileInfo(file);
						string fileInfoText = $"{fileInfo.Name},  {fileInfo.DirectoryName}\\,  {ConvertBytesToReadableSize(fileInfo.Length)} ";


						// 判断文件类型并获取时长(如果为音视频文件)
						if (IsMediaFile(fileInfo.Extension))
						{
							TimeSpan duration = GetMediaDuration(file);
							fileInfoText += $",{duration.ToString(@"hh\:mm\:ss")}";
						}
						else
						{
							fileInfoText += $",";
						}

						// 写入文件信息到文本文件
						Console.WriteLine($"文件名: {fileInfo.Name}, 大小: {ConvertBytesToReadableSize(fileInfo.Length)} 字节");
						writer.WriteLine(fileInfoText);
					}


				}

				// 获取当前目录下的所有子目录
				string[] directories = Directory.GetDirectories(path);
				foreach (string directory in directories)
				{
					// 递归调用以列出子目录中的文件,并增加递归深度
					ListFilesAndDirectories(directory, writer, currentDepth + 1);
				}
			}
			catch (UnauthorizedAccessException ex)
			{
				// 处理无权限访问的异常
				Console.WriteLine($"无法访问目录 {path}: {ex.Message}");
				writer.WriteLine($"无法访问目录 {path}: {ex.Message}");
			}
			catch (Exception ex)
			{
				// 处理其他异常
				Console.WriteLine($"处理目录 {path} 时出错: {ex.Message}");
				writer.WriteLine($"处理目录 {path} 时出错: {ex.Message}");
			}
		}




我们根据后缀名来判断下是否为音视频文件:

		/// <summary>
		/// 判断文件是否为音视频文件
		/// </summary>
		/// <param name="extension">文件扩展名</param>
		/// <returns>是否为音视频文件</returns>
		static bool IsMediaFile(string extension)
		{
			string[] mediaExtensions = { ".mp3", ".wav", ".wma", ".m4a", ".mp4", ".avi", ".mkv", ".webm", ".mov" };
			return Array.Exists(mediaExtensions, e => e.Equals(extension, StringComparison.OrdinalIgnoreCase));
		}



如果是音视频文件,返回时长:

		/// <summary>
		/// 获取音视频文件的时长
		/// </summary>
		/// <param name="filePath">音视频文件路径</param>
		/// <returns>时长</returns>
		static TimeSpan GetMediaDuration(string filePath)
		{
			try
			{
				// 使用 TagLib 获取音视频文件时长
				var file = TagLib.File.Create(filePath);
				return file.Properties.Duration;
			}
			catch (Exception ex)
			{
				Console.WriteLine($"无法获取文件 {filePath} 的时长: {ex.Message}");
				return TimeSpan.Zero;
			}
		}



最后格式化文件大小,好看一些:

		/// <summary>
		/// 将字节转换为可读的文件大小格式(如 KB, MB, GB 等)。
		/// </summary>
		/// <param name="bytes">文件大小(以字节为单位)</param>
		/// <returns>可读的文件大小格式</returns>
		static string ConvertBytesToReadableSize(long bytes)
		{
			if (bytes < 0)
			{
				throw new ArgumentException("字节数不能为负数。", nameof(bytes));
			}

			// 定义文件大小单位及其缩写
			string[] sizeUnits = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
			int unitIndex = 0;

			double size = bytes;

			// 不断除以 1024,直到找到合适的单位
			while (size >= 1024 && unitIndex < sizeUnits.Length - 1)
			{
				size /= 1024;
				unitIndex++;
			}

			// 返回带有单位的文件大小,保留两位小数
			return $"{size:0.00} {sizeUnits[unitIndex]}";
		}



最后填充下main函数,我们创建一个csv用于写入数据

		static void Main(string[] args)
		{
			DateTime d1=DateTime.Now;
			// 获取当前目录
			string currentDirectory = Directory.GetCurrentDirectory();
			ownFilePath = Process.GetCurrentProcess().MainModule.FileName;

			string filrName = $"FileList{d1.ToString("yyyyMMddHHmmss")}.csv";

			// 定义输出文件路径
			outputFilePath = Path.Combine(currentDirectory, filrName);

			// 创建或覆盖输出文件
			using (StreamWriter writer = new StreamWriter(outputFilePath, false, System.Text.Encoding.UTF8))
			{
				writer.WriteLine("文件名,路径,大小,时长");
				Console.WriteLine("文件名,路径,大小,时长");
				// 递归列出当前目录及最多3层子目录的文件
				ListFilesAndDirectories(currentDirectory, writer, 0);
			}

			Console.WriteLine("遍历完毕,按回车退出!");
			Console.ReadLine();
		}




因为我们使用了第三方的包,在AOT发布前需要处理下,给项目添加个 rd.xml 文件,把我们的第三方包集成进去,文件内容如下:

<Directives>
  <Application>
    <Assembly Name="TagLibSharp"  Dynamic="Required All">
    </Assembly>
  </Application>
</Directives>



然后修改项目文件,增加 rd.xml

image



最后就是AOT发布了

目前vs还不支持直接AOT发布(https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/aot/native-aot-tutorial?view=aspnetcore-8.0&tabs=visual-studio

需要自己手打下命令

image


到 \bin\Release\net8.0\win-x64\publish 下就能看到发布的文件了

运行下看看效果:

image


生成的csv文件:

image

posted @ 2024-09-09 13:42  sun8134  阅读(22)  评论(0编辑  收藏  举报
分享按钮