[工具类]文件或文件夹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),则返回的结果

总结

这个类确实解决了一些问题,但是针对一些恶意输入的文件或者文件夹名也是没办法的,只能在调用重命名方法之前再加上一个判断文件或者目录是否存在的情况,如果存在再走重命名方法,如果不存在则直接保存就行。

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

时间: 2024-11-07 16:36:14

[工具类]文件或文件夹xx已存在,则重命名为xx(n)的相关文章

[工具类]文件或文件夹xx已存在,则重命名为xx(n)(2)

写在前面 最近一直在弄文件传输组件,其中一个功能就是,在接收端接收文件时,如果文件已经存在了,则对其进行文件名+索引的方式进行自动重命名,之前也写个类似的工具类,总感觉代码太冗余,每回头想想,总觉得心里有疙瘩,下班的时候在地铁上,又想了想,感觉是我把问题想复杂了,遂将今天的思路整理一下,写了一个辅助类,记录在此. 上篇文章 [工具类]文件或文件夹xx已存在,则重命名为xx(n) ReNameHelper代码 1 using System; 2 using System.Collections.G

Android 工具类大全java文件

package com.clw.cosmax.utils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncoding

游戏场景需要是可配置的:AssetManager工具类和xml文件读取

我们已经知道,游戏得有个活动场景(每个场景是个可点击的button控件),并且可以通过代码生成控件的方式把活动场景进行多行多列的排列.见上篇:https://www.cnblogs.com/zzqm-gamelife/p/10254466.html 但是没有解决这样的问题: 1.场景名称需要自定义 2.版本更新,今天要加个"蟠桃园"的地图,明天活动,又加个"九重妖塔". 如果每次加个地图就要改一次代码,太麻烦了.我们选择用xml文件来做配置(PS,有条件的可以用服务

文件读取工具类读取properties文件

1.创建工具类 import java.io.IOException; import java.util.Properties; /** * * 类名称:PropertiesUtil * 类描述: 文件读取类 * 创建人:Jxufe HeHaiYang * 创建时间:2015-1-20 下午03:14:02 * 修改备注: * @version */ public class PropertiesUtil { private static Properties properties=new Pr

Http02App 整合两个工具类实现下载文件

Http02App.java1.使用两个工具类 实现下载音乐和图片到本地硬盘中 package main; import Http.FileUtils;import Http.HttpUtils; import java.io.IOException; /** * Created by lxj-pc on 2017/6/27. */public class Http02App { static String imgurl = "https://ss0.bdstatic.com/5aV1bjqh_

工具类commons-io的Tailer用来监控文件

一.前言:在Linux下有使用tail命令 在Commons-io中也提供这种方法 二.他采用的是线程方式来监控文件内容的变化 1.Tailer类(采用线程的方式进行文件的内容变法) 2.TailerListener类 3.TailerListenerAdapter类,该类是集成了TailerListener的实现空的接口方式 三.测试使用代码 [java] view plain copy package com.hadoop.leran.commons.io; import org.apach

ThinkPHP3验证码、文件上传、缩略图、分页(自定义工具类、session和cookie)

验证码 TP框架中自带了验证码类 位置:Think/verify.class.php 在LoginController控制器中创建生存验证码的方法 login.html登陆模板中 在LoginController控制器中判断验证码是否正确并且判断登陆是否成功 文件上传 用到的知识点: 1.文件上传的时候,要设置表单的enctype属性 2.$_FILE[名字][]用来接收文件的信息 第二维的字段: name size error type tmp_name 3.move_uploaded_fil

Spring 的优秀工具类盘点,第 1 部分: 文件资源操作和 Web 相关工具类

?文件资源操作 文件资源的操作是应用程序中常见的功能,如当上传一个文件后将其保存在特定目录下,从指定地址加载一个配置文件等等.我们一般使用 JDK 的 I/O 处理类完成这些操作,但对于一般的应用程序来说,JDK 的这些操作类所提供的方法过于底层,直接使用它们进行文件操作不但程序编写复杂而且容易产生错误.相比于 JDK 的 File,Spring 的 Resource 接口(资源概念的描述接口)抽象层面更高且涵盖面更广,Spring 提供了许多方便易用的资源操作工具类,它们大大降低资源操作的复杂

郑州尚学堂:php实现网页缓存的工具类分享

PHP是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域.PHP 独特的语法混合了C.Java.Perl以及PHP自创的语法.它可以比CGI或者Perl更快速地执行动态网页.今天给大家分享php实现网页缓存的工具类的代码及使用方法,非常的实用,希望可以对有需求的小伙伴带来帮助. php程序在抵抗大流量访问的时候动态网站往往都是难以招架,所以要引入缓存机制,一般情况下有两种类型缓存 一.文件缓存 二.数据查询结果缓存,使用内存来实现高速