[工具類]文件或文件夾xx已存在,則重命名為xx(n)


寫在前面

最近在弄一個文件傳輸的一個東東,在接收文件的時候,如果文件已經存在,該如何處理?提示?刪除?感覺直接刪除實在不太合適,萬一這個文件對用戶來說很重要,你給他刪除了肯定不行。然后就想到了,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),則返回的結果

總結

這個類確實解決了一些問題,但是針對一些惡意輸入的文件或者文件夾名也是沒辦法的,只能在調用重命名方法之前再加上一個判斷文件或者目錄是否存在的情況,如果存在再走重命名方法,如果不存在則直接保存就行。

如果您有更好的方式,請留言。

也許你會看這篇文章:

[工具類]文件或文件夾xx已存在,則重命名為xx(n)(2)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM