寫在前面
最近在弄一個文件傳輸的一個東東,在接收文件的時候,如果文件已經存在,該如何處理?提示?刪除?感覺直接刪除實在不太合適,萬一這個文件對用戶來說很重要,你給他刪除了肯定不行。然后就想到了,windows系統在新建文件的時候,如果文件存在就以(n)這樣的形式創建。當時覺得這種方式確實不錯,查找了windows的api,未果,然后就想如果讓自己實現,該如何去實現?
工具類
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.SaveAs 10 { 11 /// <summary> 12 /// 重命名輔助類 13 /// </summary> 14 public class ReNameHelper 15 { 16 /// <summary> 17 /// 保存同名文件時,進行重命名操作. 18 /// 例如文件夾內已存在1.txt,則再次保存時保存為1(1).txt,....1(n).txt 19 /// </summary> 20 /// <param name="strFolderPath">保存的目錄</param> 21 /// <param name="strFileName">文件名</param> 22 /// <returns>新的文件名</returns> 23 public static string ReFileName(string strFolderPath, string strFileName) 24 { 25 //當前傳進的文件名自帶的索引 26 int intCurrentFileIndex = 0; 27 string strNewName = string.Empty; 28 //用來保存當前目錄下的文件的最大索引。 29 int intMaxIndex = 0; 30 //如果文件不存在,直接返回 31 if (!File.Exists(Path.Combine(strFolderPath, strFileName))) 32 { 33 return strFileName; 34 } 35 //根據傳進來的文件名,獲取擴展名 36 string strExtention = Path.GetExtension(strFileName); 37 string strFileNameWithoutExtion = Path.GetFileNameWithoutExtension(strFileName); 38 //如果文件名中本身就包括括號,則需要還原原來的文件名 39 string strNameContainsBracketsRegex = "(?<fileName>.+?)" + "([((](?<fileNameIndex>\\d+)[))])" + strExtention; 40 Regex regexContain = new Regex(strNameContainsBracketsRegex, RegexOptions.Singleline); 41 if (regexContain.IsMatch(strFileName)) 42 { 43 Match match = regexContain.Match(strFileName); 44 strFileNameWithoutExtion = match.Groups["fileName"].Value; 45 intCurrentFileIndex = Convert.ToInt32(match.Groups["fileNameIndex"].Value); 46 } 47 //根據傳進來的文件名,通過正則匹配,找到類似的文件名,不區別中英文的括號並且括號及索引可有可無 48 string strRegex = strFileNameWithoutExtion + "([((](?<fileNameIndex>\\d+)[))])" + strExtention; 49 Regex regex = new Regex(strRegex, RegexOptions.Singleline); 50 string[] strFileNames = Directory.GetFiles(strFolderPath, "*" + strExtention) 51 .Where(x => regex.IsMatch(x) || x.Contains(strFileNameWithoutExtion)) 52 .ToArray(); 53 if (strFileNames != null && strFileNames.Length > 0) 54 { 55 foreach (string item in strFileNames) 56 { 57 //因為獲得的文件路徑數組中都是匹配成功的路徑,此處不再進行判斷是否匹配 58 Match match = regex.Match(item); 59 //獲得索引 60 string strIndex = match.Groups["fileNameIndex"].Value; 61 //如果為空,說明只有類似 1.txt這樣的文件,則返回的文件就是1(1).txt 62 //否則找到最大索引,然后拼接最大索引加一的文件名 63 if (!string.IsNullOrEmpty(strIndex)) 64 { 65 int intIndex = Convert.ToInt32(strIndex); 66 if (intMaxIndex < intIndex) 67 { 68 intMaxIndex = intIndex; 69 } 70 } 71 } 72 //如果目錄中存在的文件索引大於或者等於當前傳進來的文件的索引則使用新的名稱,否則將返回傳進來的文件名稱 73 if (intMaxIndex >= intCurrentFileIndex) 74 { 75 //循環接收,求出了最大的索引,則新文件的索引就是最大索引加一 76 StringBuilder sb = new StringBuilder(); 77 sb.Append(strFileNameWithoutExtion); 78 sb.Append("("); 79 sb.Append((intMaxIndex + 1).ToString()); 80 sb.Append(")"); 81 sb.Append(strExtention); 82 strNewName = sb.ToString(); 83 } 84 else 85 { 86 strNewName = strFileName; 87 } 88 } 89 else 90 { 91 //如果沒有匹配到相似的文件名結構,則說明是一個新的文件,則不做任何操作 92 strNewName = strFileName; 93 } 94 return strNewName; 95 } 96 /// <summary> 97 /// 保存同名文件夾時,進行重命名操作. 98 /// 例如文件夾內已存在1的文件夾,則再次保存時保存為1(1),....1(n) 99 /// </summary> 100 /// <param name="strFolderPath">保存的目錄</param> 101 /// <param name="strFolderPath">保存的目錄</param> 102 /// <returns>新的目錄名</returns> 103 public static string ReFolderName(string strFolderPath, string strFolderName) 104 { 105 //當前傳進的文件夾自帶的索引 106 int intCurrentFolderIndex = 0; 107 string strNewName = string.Empty; 108 //原始名字 109 string strOriginalName = strFolderName; 110 //用來保存當前目錄下的文件的最大索引。 111 int intMaxIndex = 0; 112 if (!Directory.Exists(Path.Combine(strFolderPath, strFolderName))) 113 { 114 return strFolderName; 115 } 116 //根據傳進來的文件名,通過正則匹配,找到文件夾是否已經帶有索引。 117 string strRegex = "(?<folderName>.+?)([((](?<folderIndex>\\d+)[))])"; 118 Regex regex = new Regex(strRegex, RegexOptions.Singleline); 119 if (regex.IsMatch(strFolderName)) 120 { 121 Match match = regex.Match(strFolderName); 122 string strFolderIndex = match.Groups["folderIndex"].Value; 123 if (!string.IsNullOrEmpty(strFolderIndex)) 124 { 125 intCurrentFolderIndex = Convert.ToInt32(strFolderIndex); 126 strOriginalName = match.Groups["folderName"].Value; 127 } 128 } 129 130 string[] strFolderNames = Directory.GetDirectories(strFolderPath) 131 .Where(x => regex.IsMatch(x)) 132 .Select(x => x.Split(new char[] { '\\' }) 133 .LastOrDefault()) 134 .ToArray(); 135 if (strFolderNames != null && strFolderNames.Length > 0) 136 { 137 foreach (string item in strFolderNames) 138 { 139 //因為獲得的文件路徑數組中都是匹配成功的路徑,此處不再進行判斷是否匹配 140 Match match = regex.Match(item); 141 //獲得索引 142 string strIndex = match.Groups["folderIndex"].Value; 143 //如果為空,說明只有類似 1.txt這樣的文件,則返回的文件就是1(1).txt 144 //否則找到最大索引,然后拼接最大索引加一的文件名 145 if (!string.IsNullOrEmpty(strIndex)) 146 { 147 int intIndex = Convert.ToInt32(strIndex); 148 if (intMaxIndex < intIndex) 149 { 150 intMaxIndex = intIndex; 151 } 152 } 153 } 154 //如果目錄中存在的文件索引大於或者等於當前傳進來的文件的索引則使用新的名稱,否則將返回傳進來的文件名稱 155 if (intMaxIndex >= intCurrentFolderIndex) 156 { 157 //循環接收,求出了最大的索引,則新文件的索引就是最大索引加一 158 StringBuilder sb = new StringBuilder(); 159 sb.Append(strOriginalName); 160 sb.Append("("); 161 sb.Append((intMaxIndex + 1).ToString()); 162 sb.Append(")"); 163 strNewName = sb.ToString(); 164 } 165 else 166 { 167 strNewName = strFolderName; 168 } 169 } 170 else 171 { 172 //如果沒有匹配到相似的文件名結構,則說明是一個新的文件,則不做任何操作 173 strNewName = strFolderName; 174 } 175 return strNewName; 176 } 177 } 178 }
測試
測試用的保存的目錄,結構如下:
測試
如果接收的文件為1.txt,則獲取到的新文件名1(2).txt,因為與1.txt名稱相似的文件已經存在的最大文件索引為1.
如果接收的文件夾名稱為新建文件夾,則獲取到的新文件夾名為新建文件夾(3),因為與新建文件夾名稱相似的文件夾的最大索引為2。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 string newName =ReNameHelper.ReFileName(@"C:\Users\Wolfy\Desktop\Test", "1.txt"); 6 string strNewFolderName = ReNameHelper.ReFolderName(@"C:\Users\Wolfy\Desktop\Test\", "新建文件夾"); 7 Console.WriteLine(newName); 8 Console.WriteLine(strNewFolderName); 9 Console.ReadKey(); 10 } 11 }
測試結果
如果接收的文件為1(1).txt,則獲取到的新文件名1(2).txt,因為與1(1).txt名稱相似的文件已經存在的最大文件索引為1.
如果接收的文件夾名稱為新建文件夾(1),則獲取到的新文件夾名為新建文件夾(3),因為與新建文件夾名稱相似的文件夾的最大索引為2。
測試結果
如果接收的文件為1(2).txt,則獲取到的新文件名1(2).txt,因為與1.txt名稱相似的文件已經存在的最大文件索引為1.(傳進來的文件名中帶的索引大於已經存在的索引)
如果接收的文件夾名稱為新建文件夾(1),則獲取到的新文件夾名為新建文件夾(3),因為與新建文件夾名稱相似的文件夾的最大索引為2(這里在調用該方法的時候,可以首先判斷一下該目錄是否存在,如果不存在,直接創建不再走該方法,那么保存的文件名為:新建文件夾(1))。
如果接收的文件夾名稱為新建文件夾(3),索引大於已經存在的文件夾的最大索引,則保存為新建文件夾(3)
這里只對文件名為1(1)(1).txt的做了處理,文件夾的以類似新建文件夾(n)這樣的名稱為主。
1 static void Main(string[] args) 2 { 3 string newName = ReNameHelper.ReFileName(@"C:\Users\Wolfy\Desktop\Test", "1(1)(2).txt"); 4 string strNewFolderName = ReNameHelper.ReFolderName(@"C:\Users\Wolfy\Desktop\Test\", "新建文件夾 (2) (1)"); 5 Console.WriteLine(newName); 6 Console.WriteLine(strNewFolderName); 7 Console.ReadKey(); 8 }
如果test目錄下已經存在:1(1)(2).txt和新建文件夾 (2) (1),則返回的結果
總結
這個類確實解決了一些問題,但是針對一些惡意輸入的文件或者文件夾名也是沒辦法的,只能在調用重命名方法之前再加上一個判斷文件或者目錄是否存在的情況,如果存在再走重命名方法,如果不存在則直接保存就行。
如果您有更好的方式,請留言。
也許你會看這篇文章: