写在前面
最近一直在弄文件传输组件,其中一个功能就是,在接收端接收文件时,如果文件已经存在了,则对其进行文件名+索引的方式进行自动重命名,之前也写个类似的工具类,总感觉代码太冗余,每回头想想,总觉得心里有疙瘩,下班的时候在地铁上,又想了想,感觉是我把问题想复杂了,遂将今天的思路整理一下,写了一个辅助类,记录在此。
上篇文章
ReNameHelper代码
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Text; 6 using System.Text.RegularExpressions; 7 using System.Threading.Tasks; 8 9 namespace Wolfy.ReNameHelper 10 { 11 /// <summary> 12 /// 文件已存在,重命名操作类 13 /// </summary> 14 public class ReNameHelper 15 { 16 /// <summary> 17 /// 对文件进行重命名 18 /// </summary> 19 /// <param name="strFilePath"></param> 20 /// <returns></returns> 21 public static string FileReName(string strFilePath) 22 { 23 //判断该文件是否存在,存在则返回新名字,否则返回原来的名 24 if (!File.Exists(strFilePath)) 25 { 26 return Path.GetFileName(strFilePath); 27 } 28 else 29 { 30 //获取不带扩展名的文件名称 31 string strFileNameWithoutExtension = Path.GetFileNameWithoutExtension(strFilePath); 32 //获取扩展名 33 string strFileExtension = Path.GetExtension(strFilePath); 34 //获取目录名 35 string strDirPath = Path.GetDirectoryName(strFilePath); 36 //以文件名开头和结尾的正则 37 string strRegex = "^" + strFileNameWithoutExtension + "(\d+)?" ; 38 Regex regex = new Regex(strRegex); 39 //获取该路径下类似的文件名 40 string[] strFilePaths = Directory.GetFiles(strDirPath, "*" + strFileExtension).Where(path => regex.IsMatch(Path.GetFileNameWithoutExtension(path))).ToArray(); 41 //获得新的文件名 42 return strFileNameWithoutExtension + "(" + (strFilePaths.Length + 1).ToString() + ")" + strFileExtension; 43 } 44 } 45 /// <summary> 46 /// 文件夹已存在,重命名 47 /// </summary> 48 /// <param name="strFolderPath"></param> 49 /// <returns></returns> 50 public static string FolderReName(string strFolderPath) 51 { 52 //判断该文件夹是否存在,存在则返回新名字,否则返回原来的名 53 if (!Directory.Exists(strFolderPath)) 54 { 55 return Path.GetFileName(strFolderPath); 56 } 57 else 58 { 59 //获取文件夹名 60 string strFolderName= Path.GetFileName(strFolderPath); 61 //获取目录名 62 string strDirPath = Path.GetDirectoryName(strFolderPath); 63 //以文件夹名开头和结尾的正则 64 string strRegex = "^" + strFolderName + "(\d+)?"; 65 Regex regex = new Regex(strRegex); 66 //获取该路径下类似的文件夹名 67 string[] strFilePaths = Directory.GetDirectories(strDirPath).Where(path => regex.IsMatch(Path.GetFileName(path))).ToArray(); 68 //获得新的文件名 69 return strFolderName + "(" + (strFilePaths.Length + 1).ToString() + ")" ; 70 } 71 } 72 } 73 }
实现思路:使用正则进行匹配以文件名或者文件夹名字开头的文件或者文件夹名称,获取文件或者文件夹的个数,则新的文件名为文件名(文件或者文件夹总数+1)。当然,对一些,名字比较特殊的,不符合windows命名规则的,在客户端选择文件或者文件夹的时候,尽量对其进行过滤。以保证该辅助类起到应有的作用。
简单测试
在路径C:UsersWolfyDesktopMVC5下有如上图的一些文件,现在如果再次接收相同名字的文件或者文件夹,则返回新的文件或者文件夹名
结果
这里也分享一个园友写的一个重命名的辅助类。对文件操作的辅助类,记录再次,供大家参考。
原文地址:http://www.cnblogs.com/lxblog/archive/2012/11/13/2768096.html
using System; using System.Runtime.InteropServices; using System.IO; namespace LxFile { /// <summary> /// 文件操作代理,该类提供类似于Windows的文件操作体验 /// </summary> public class FileOperateProxy { #region 【内部类型定义】 private struct SHFILEOPSTRUCT { public IntPtr hwnd; //父窗口句柄 public wFunc wFunc; //要执行的动作 public string pFrom; //源文件路径,可以是多个文件,以结尾符号" "结束 public string pTo; //目标路径,可以是路径或文件名 public FILEOP_FLAGS fFlags; //标志,附加选项 public bool fAnyOperationsAborted; //是否可被中断 public IntPtr hNameMappings; //文件映射名字,可在其它 Shell 函数中使用 public string lpszProgressTitle; // 只在 FOF_SIMPLEPROGRESS 时,指定对话框的标题。 } private enum wFunc { FO_MOVE = 0x0001, //移动文件 FO_COPY = 0x0002, //复制文件 FO_DELETE = 0x0003, //删除文件,只是用pFrom FO_RENAME = 0x0004 //文件重命名 } private enum FILEOP_FLAGS { FOF_MULTIDESTFILES = 0x0001, //pTo 指定了多个目标文件,而不是单个目录 FOF_CONFIRMMOUSE = 0x0002, FOF_SILENT = 0x0044, // 不显示一个进度对话框 FOF_RENAMEONCOLLISION = 0x0008, // 碰到有抵触的名字时,自动分配前缀 FOF_NOCONFIRMATION = 0x10, // 不对用户显示提示 FOF_WANTMAPPINGHANDLE = 0x0020, // 填充 hNameMappings 字段,必须使用 SHFreeNameMappings 释放 FOF_ALLOWUNDO = 0x40, // 允许撤销 FOF_FILESONLY = 0x0080, // 使用 *.* 时, 只对文件操作 FOF_SIMPLEPROGRESS = 0x0100, // 简单进度条,意味者不显示文件名。 FOF_NOCONFIRMMKDIR = 0x0200, // 建新目录时不需要用户确定 FOF_NOERRORUI = 0x0400, // 不显示出错用户界面 FOF_NOCOPYSECURITYATTRIBS = 0x0800, // 不复制 NT 文件的安全属性 FOF_NORECURSION = 0x1000 // 不递归目录 } #endregion 【内部类型定义】 #region 【DllImport】 [DllImport("shell32.dll")] private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp); #endregion 【DllImport】 #region 【删除文件操作】 /// <summary> /// 删除单个文件。 /// </summary> /// <param name="fileName">删除的文件名</param> /// <param name="toRecycle">指示是将文件放入回收站还是永久删除,true-放入回收站,false-永久删除</param> /// <param name="showDialog">指示是否显示确认对话框,true-显示确认删除对话框,false-不显示确认删除对话框</param> /// <param name="showProgress">指示是否显示进度对话框,true-显示,false-不显示。该参数当指定永久删除文件时有效</param> /// <param name="errorMsg">反馈错误消息的字符串</param> /// <returns>操作执行结果标识,删除文件成功返回0,否则,返回错误代码</returns> public static int DeleteFile(string fileName, bool toRecycle, bool showDialog, bool showProgress, ref string errorMsg) { try { string fName = GetFullName(fileName); return ToDelete(fName, toRecycle, showDialog, showProgress, ref errorMsg); } catch (Exception ex) { errorMsg = ex.Message; return -200; } } /// <summary> /// 删除一组文件。 /// </summary> /// <param name="fileNames">字符串数组,表示一组文件名</param> /// <param name="toRecycle">指示是将文件放入回收站还是永久删除,true-放入回收站,false-永久删除</param> /// <param name="showDialog">指示是否显示确认对话框,true-显示确认删除对话框,false-不显示确认删除对话框</param> /// <param name="showProgress">指示是否显示进度对话框,true-显示,false-不显示。该参数当指定永久删除文件时有效</param> /// <param name="errorMsg">反馈错误消息的字符串</param> /// <returns>操作执行结果标识,删除文件成功返回0,否则,返回错误代码</returns> public static int DeleteFiles(string[] fileNames, bool toRecycle, bool showDialog, bool showProgress, ref string errorMsg) { try { string fName = ""; foreach (string str in fileNames) { fName += GetFullName(str) + "