508 lines
20 KiB
C#
508 lines
20 KiB
C#
using hyjiacan.py4n;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace DH.Commons.Enums
|
||
{
|
||
|
||
public static class FileHelper
|
||
{
|
||
|
||
/// <summary>
|
||
/// 清理两个文件夹中的文件,保留文件名交集部分,其余文件删除。
|
||
/// </summary>
|
||
/// <param name="imagesFolder">图片文件夹路径</param>
|
||
/// <param name="labelsFolder">标签文件夹路径</param>
|
||
public static void CleanupFolders(string imagesFolder, string labelsFolder)
|
||
{
|
||
if (!Directory.Exists(imagesFolder))
|
||
{
|
||
Console.WriteLine($"Images folder does not exist: {imagesFolder}");
|
||
return;
|
||
}
|
||
|
||
if (!Directory.Exists(labelsFolder))
|
||
{
|
||
Console.WriteLine($"Labels folder does not exist: {labelsFolder}");
|
||
return;
|
||
}
|
||
|
||
// 获取文件名(不包含扩展名)
|
||
var imageFiles = Directory.GetFiles(imagesFolder)
|
||
.Select(Path.GetFileNameWithoutExtension)
|
||
.ToHashSet();
|
||
|
||
var labelFiles = Directory.GetFiles(labelsFolder)
|
||
.Select(Path.GetFileNameWithoutExtension)
|
||
.ToHashSet();
|
||
|
||
// 计算交集
|
||
var commonFiles = imageFiles.Intersect(labelFiles);
|
||
|
||
// 删除 images 文件夹中不在交集中的文件
|
||
foreach (var imagePath in Directory.GetFiles(imagesFolder))
|
||
{
|
||
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(imagePath);
|
||
if (!commonFiles.Contains(fileNameWithoutExt))
|
||
{
|
||
File.Delete(imagePath);
|
||
Console.WriteLine($"Deleted image file: {imagePath}");
|
||
}
|
||
}
|
||
|
||
// 删除 labels 文件夹中不在交集中的文件
|
||
foreach (var labelPath in Directory.GetFiles(labelsFolder))
|
||
{
|
||
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(labelPath);
|
||
if (!commonFiles.Contains(fileNameWithoutExt))
|
||
{
|
||
File.Delete(labelPath);
|
||
Console.WriteLine($"Deleted label file: {labelPath}");
|
||
}
|
||
}
|
||
|
||
Console.WriteLine("Folders cleaned successfully!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取文件夹中所有图片文件的个数
|
||
/// </summary>
|
||
/// <param name="folderPath">目标文件夹路径</param>
|
||
/// <param name="includeSubdirectories">是否包含子文件夹,默认不包含</param>
|
||
/// <returns>图片文件总数</returns>
|
||
public static int CountImageFiles(string folderPath, bool includeSubdirectories = false)
|
||
{
|
||
if (!Directory.Exists(folderPath))
|
||
{
|
||
throw new DirectoryNotFoundException($"The folder '{folderPath}' does not exist.");
|
||
}
|
||
|
||
// 支持的图片格式
|
||
string[] imageExtensions = { "*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif" };
|
||
|
||
// 搜索选项
|
||
SearchOption searchOption = includeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||
|
||
int fileCount = 0;
|
||
|
||
foreach (var ext in imageExtensions)
|
||
{
|
||
fileCount += Directory.GetFiles(folderPath, ext, searchOption).Length;
|
||
}
|
||
|
||
return fileCount;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除一个目录所有子目录和文件
|
||
/// </summary>
|
||
/// <param name="path"></param>
|
||
public static void DeleteDirectoryAndContents(string path)
|
||
{
|
||
// 确保目录存在
|
||
if (Directory.Exists(path))
|
||
{
|
||
// 删除目录中的文件
|
||
string[] files = Directory.GetFiles(path);
|
||
foreach (var file in files)
|
||
{
|
||
File.Delete(file);
|
||
Console.WriteLine($"文件已删除: {file}");
|
||
}
|
||
|
||
// 删除目录中的子目录
|
||
string[] directories = Directory.GetDirectories(path);
|
||
foreach (var directory in directories)
|
||
{
|
||
DeleteDirectoryAndContents(directory); // 递归删除子目录
|
||
}
|
||
|
||
// 删除空目录
|
||
Directory.Delete(path);
|
||
Console.WriteLine($"目录已删除: {path}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("目录不存在!");
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 将一个文件夹中的所有图片文件和 JSON 文件复制到另一个文件夹中
|
||
/// </summary>
|
||
/// <param name="sourceDirectory"></param>
|
||
/// <param name="destinationDirectory"></param>
|
||
public static void CopyImageAndJsonFiles(string sourceDirectory, string destinationDirectory)
|
||
{
|
||
// 确保目标文件夹存在,如果不存在则创建它
|
||
if (!Directory.Exists(destinationDirectory))
|
||
{
|
||
Directory.CreateDirectory(destinationDirectory);
|
||
}
|
||
|
||
// 获取源文件夹中的所有图片文件和 JSON 文件
|
||
string[] imageFiles = Directory.GetFiles(sourceDirectory, "*.*")
|
||
.Where(file => file.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
|
||
file.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) ||
|
||
file.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
|
||
file.EndsWith(".gif", StringComparison.OrdinalIgnoreCase) ||
|
||
file.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) ||
|
||
file.EndsWith(".tiff", StringComparison.OrdinalIgnoreCase) ||
|
||
file.EndsWith(".webp", StringComparison.OrdinalIgnoreCase))
|
||
.ToArray();
|
||
|
||
string[] jsonFiles = Directory.GetFiles(sourceDirectory, "*.json");
|
||
|
||
// 合并图片文件和 JSON 文件
|
||
string[] filesToCopy = imageFiles.Concat(jsonFiles).ToArray();
|
||
|
||
foreach (string file in filesToCopy)
|
||
{
|
||
try
|
||
{
|
||
// 获取文件名
|
||
string fileName = Path.GetFileName(file);
|
||
|
||
// 拼接目标文件的完整路径
|
||
string destinationFile = Path.Combine(destinationDirectory, fileName);
|
||
|
||
// 如果目标文件已存在,可以选择覆盖或跳过(这里我们选择跳过)
|
||
if (File.Exists(destinationFile))
|
||
{
|
||
Console.WriteLine($"文件 {fileName} 已存在,跳过复制.");
|
||
continue;
|
||
}
|
||
|
||
// 复制文件
|
||
File.Copy(file, destinationFile);
|
||
Console.WriteLine($"文件 {fileName} 已成功复制到 {destinationDirectory}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"复制文件 {file} 时出错: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 遍历图片文件夹,检查对应的标签文件夹中是否有同名的 .txt 文件。
|
||
/// 如果没有,则创建一个空的 .txt 文件。
|
||
/// </summary>
|
||
/// <param name="imagesDirectory">图片文件夹路径</param>
|
||
/// <param name="labelsDirectory">标签文件夹路径</param>
|
||
public static void ProcessImageFiles(string imagesDirectory, string labelsDirectory)
|
||
{
|
||
// 检查 images 目录是否存在
|
||
if (!Directory.Exists(imagesDirectory))
|
||
{
|
||
throw new DirectoryNotFoundException($"目录 {imagesDirectory} 不存在.");
|
||
}
|
||
|
||
// 检查 labels 目录是否存在,如果不存在则创建
|
||
if (!Directory.Exists(labelsDirectory))
|
||
{
|
||
Directory.CreateDirectory(labelsDirectory);
|
||
Console.WriteLine($"目录 {labelsDirectory} 已创建.");
|
||
}
|
||
|
||
// 获取 images 目录中的所有文件(包括图片文件)
|
||
string[] imageFiles = Directory.GetFiles(imagesDirectory, "*.*", SearchOption.TopDirectoryOnly);
|
||
string[] validExtensions = { ".jpg", ".jpeg", ".png", ".bmp", ".gif" }; // 支持的图片格式
|
||
|
||
foreach (var imageFile in imageFiles)
|
||
{
|
||
// 检查文件扩展名是否为支持的图片格式
|
||
string extension = Path.GetExtension(imageFile).ToLower();
|
||
if (Array.Exists(validExtensions, ext => ext == extension))
|
||
{
|
||
// 获取图片文件的文件名(不包括扩展名)
|
||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(imageFile);
|
||
|
||
// 生成对应的 txt 文件路径
|
||
string labelFilePath = Path.Combine(labelsDirectory, fileNameWithoutExtension + ".txt");
|
||
|
||
// 如果该 txt 文件不存在,则创建一个空白 txt 文件
|
||
if (!File.Exists(labelFilePath))
|
||
{
|
||
try
|
||
{
|
||
File.WriteAllText(labelFilePath, string.Empty); // 创建空白 txt 文件
|
||
Console.WriteLine($"创建空白文件: {labelFilePath}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"无法创建文件 {labelFilePath}: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 封装的函数:删除没有对应 JSON 文件的图片
|
||
public static void DeleteUnmatchedImages(string labelsFolderPath, string imagesFolderPath)
|
||
{
|
||
try
|
||
{
|
||
// 获取 labels 文件夹中的所有 JSON 文件名(去除扩展名)
|
||
string[] jsonFiles = Directory.GetFiles(labelsFolderPath, "*.txt");
|
||
HashSet<string> jsonFileNames = new HashSet<string>();
|
||
|
||
foreach (string jsonFile in jsonFiles)
|
||
{
|
||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(jsonFile);
|
||
jsonFileNames.Add(fileNameWithoutExtension);
|
||
}
|
||
|
||
// 获取 images 文件夹中的所有图片文件
|
||
string[] imageFiles = Directory.GetFiles(imagesFolderPath);
|
||
|
||
// 遍历图片文件,检查是否有对应的 JSON 文件
|
||
foreach (string imageFile in imageFiles)
|
||
{
|
||
string imageFileNameWithoutExtension = Path.GetFileNameWithoutExtension(imageFile);
|
||
|
||
// 如果图片文件名不在 labels 文件夹的 JSON 文件名集合中,则删除该图片
|
||
if (!jsonFileNames.Contains(imageFileNameWithoutExtension))
|
||
{
|
||
try
|
||
{
|
||
File.Delete(imageFile); // 删除图片
|
||
Console.WriteLine($"已删除图片: {Path.GetFileName(imageFile)}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"删除文件 {Path.GetFileName(imageFile)} 时出错: {ex.Message}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"图片 {Path.GetFileName(imageFile)} 有对应的 JSON 文件,不删除。");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"操作失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将 List<string> 保存到指定文件中,格式为 "项,标签"。
|
||
/// 标签是根据项的索引生成的。
|
||
/// </summary>
|
||
/// <param name="items">要保存的字符串列表</param>
|
||
/// <param name="filePath">保存文件的路径</param>
|
||
public static void SaveItemsToFile(List<string> items, string filePath)
|
||
{
|
||
// 使用 StreamWriter 写入文件
|
||
using (StreamWriter writer = new StreamWriter(filePath))
|
||
{
|
||
// 遍历 items 列表
|
||
for (int i = 0; i < items.Count; i++)
|
||
{
|
||
// 写入每一行,格式为 "项, 标签"
|
||
writer.WriteLine($"{items[i]},{i}");
|
||
}
|
||
}
|
||
}
|
||
public static void SaveItemsToFile(HashSet<string> items, string filePath)
|
||
{
|
||
// 使用 StreamWriter 写入文件
|
||
using (StreamWriter writer = new StreamWriter(filePath))
|
||
{
|
||
// 遍历 HashSet
|
||
int i = 0;
|
||
foreach (string item in items)
|
||
{
|
||
// 写入每一行,格式为 "项, 标签"
|
||
writer.WriteLine($"{item},{i}"); // 假设使用 item 的长度作为标签
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
static List<FileInformation> FileList = new List<FileInformation>();
|
||
|
||
/// <summary>
|
||
/// 递归获取指定文件夹下所有文件
|
||
/// </summary>
|
||
/// <param name="dir"></param>
|
||
/// <returns></returns>
|
||
public static List<FileInformation> GetAllFiles(DirectoryInfo dir)
|
||
{
|
||
FileInfo[] allFile = dir.GetFiles();
|
||
foreach (FileInfo fi in allFile)
|
||
{
|
||
FileList.Add(new FileInformation { FileName = fi.Name, FilePath = fi.FullName });
|
||
}
|
||
DirectoryInfo[] allDir = dir.GetDirectories();
|
||
foreach (DirectoryInfo d in allDir)
|
||
{
|
||
GetAllFiles(d);
|
||
}
|
||
return FileList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断字符串是否纯字母
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
public static bool IsAlphabetOnly(string input)
|
||
{
|
||
return Regex.IsMatch(input, "^[a-zA-Z]+$");
|
||
}
|
||
/// <summary>
|
||
/// 判断字符串是否仅包含大小写字母和数字
|
||
/// </summary>
|
||
/// <param name="input">待判断的字符串</param>
|
||
/// <returns>如果字符串仅包含字母和数字,返回 true;否则返回 false</returns>
|
||
public static bool IsAlphaNumericOnly(string input)
|
||
{
|
||
return Regex.IsMatch(input, "^[a-zA-Z0-9]+$");
|
||
}
|
||
public static string ConvertHanzitoPinyinWithNumbers(string input)
|
||
{
|
||
// 正则表达式匹配汉字
|
||
string pattern = @"[\u4e00-\u9fa5]";
|
||
Regex regex = new Regex(pattern);
|
||
|
||
StringBuilder result = new StringBuilder();
|
||
int lastIndex = 0;
|
||
|
||
foreach (Match match in regex.Matches(input))
|
||
{
|
||
// 将非汉字部分保留为原样
|
||
result.Append(input.Substring(lastIndex, match.Index - lastIndex));
|
||
|
||
// 获取汉字并转换为拼音
|
||
string hanzi = match.Value;
|
||
string pinyin = ConvertHanziToPinyin(hanzi);
|
||
|
||
// 将拼音追加到结果中
|
||
result.Append(pinyin);
|
||
|
||
lastIndex = match.Index + match.Length;
|
||
}
|
||
|
||
// 添加最后的非汉字部分
|
||
result.Append(input.Substring(lastIndex));
|
||
|
||
return result.ToString();
|
||
}
|
||
|
||
public static string ConvertHanziToPinyin(string hanzi)
|
||
{
|
||
// 设置拼音格式:去掉音调,拼音小写,ü保持为u:
|
||
PinyinFormat format = PinyinFormat.WITHOUT_TONE | PinyinFormat.LOWERCASE | PinyinFormat.WITH_U_AND_COLON;
|
||
|
||
// 获取拼音数组
|
||
List<PinyinItem> pinyinItems = Pinyin4Net.GetPinyinArray(hanzi, format);
|
||
|
||
StringBuilder pinyinBuilder = new StringBuilder();
|
||
|
||
foreach (var item in pinyinItems)
|
||
{
|
||
// 处理多音字:默认取第一个拼音
|
||
if (item.Count > 0)
|
||
{
|
||
string pinyin = item[0];
|
||
|
||
// 特殊处理ü的情况
|
||
pinyin = pinyin.Replace("u:", "v"); // 将u:转为v,这是常见的拼音表示法
|
||
|
||
pinyinBuilder.Append(pinyin);
|
||
}
|
||
}
|
||
|
||
return pinyinBuilder.ToString();
|
||
}
|
||
/// <summary>
|
||
/// 汉字拼音转化
|
||
/// </summary>
|
||
/// <param name="hanzi"></param>
|
||
/// <returns></returns>
|
||
//public static string ConvertHanzitoPinyin(string hanzi)
|
||
//{
|
||
// PinyinFormat format = PinyinFormat.WITHOUT_TONE | PinyinFormat.LOWERCASE | PinyinFormat.WITH_U_UNICODE;
|
||
|
||
// // string hanzi = defectRow.LabelDescription;
|
||
// List<PinyinItem> pylist = Pinyin4Net.GetPinyinArray(hanzi, format);
|
||
// // 提取所有拼音并合并为一个字符串
|
||
// List<string> pinyinStrings = new List<string>();
|
||
// foreach (var item in pylist)
|
||
// {
|
||
// // 将PinyinItem中的每个拼音(List<string>)合并为一个字符串
|
||
// string joinedPinyin = string.Join("", item); // 这里的item就是一个List<string>,其中存储了拼音
|
||
// pinyinStrings.Add(joinedPinyin); // 添加合并后的拼音
|
||
// }
|
||
|
||
// // 合并所有拼音为一个字符串
|
||
// string allPinyin = string.Join("", pinyinStrings);
|
||
// return allPinyin;
|
||
//}
|
||
/// <summary>
|
||
/// 递归获取指定文件夹下所有文件
|
||
/// </summary>
|
||
/// <param name="dir"></param>
|
||
/// <returns></returns>
|
||
public static List<FileInformation> GetAllFiles(string dir)
|
||
{
|
||
DirectoryInfo directoryInfo = new(dir);
|
||
return GetAllFiles(directoryInfo);
|
||
}
|
||
public static string OpenSlectDirDialog(string dirpath = "")
|
||
{
|
||
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
||
fbd.InitialDirectory = dirpath;
|
||
if (fbd.ShowDialog() == DialogResult.OK)
|
||
{
|
||
string targetDirPath = fbd.SelectedPath;
|
||
if (Directory.Exists(targetDirPath))
|
||
{
|
||
return targetDirPath;
|
||
}
|
||
else
|
||
return string.Empty;
|
||
//ImportDirImages(targetDirPath);
|
||
}
|
||
else
|
||
return string.Empty;
|
||
}
|
||
public static string OpenSlectfileDialog(string dirpath = "")
|
||
{
|
||
|
||
|
||
|
||
// 创建并配置 OpenFileDialog 实例
|
||
OpenFileDialog openFileDialog = new OpenFileDialog();
|
||
openFileDialog.Title = "选择文件"; // 对话框标题
|
||
openFileDialog.Filter = "所有文件 (*.pt)|*.*"; // 允许选择任何类型的文件
|
||
openFileDialog.InitialDirectory = @"C:\"; // 初始显示目录,可以根据需要修改
|
||
|
||
// 显示对话框
|
||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
// 获取选中的文件路径
|
||
string selectedFilePath = openFileDialog.FileName;
|
||
Console.WriteLine("您选择的文件路径是: " + selectedFilePath);
|
||
return selectedFilePath;
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("没有选择任何文件。");
|
||
return string.Empty;
|
||
MessageBox.Show("没有选择任何文件。");
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class FileInformation
|
||
{
|
||
public string FileName { get; set; }
|
||
public string FilePath { get; set; }
|
||
}
|
||
}
|