我有这段代码:
public void FileCleanup(List<string> paths)
{
string regPattern = (@"[~#&!%+{}]+");
string replacement = "";
string replacement_unique = "_";
Regex regExPattern = new Regex(regPattern);
List<string> existingNames = new List<string>();
StreamWriter errors = new StreamWriter(@"C:\Documents and Settings\jane.doe\Desktop\SharePointTesting\Errors.txt");
StreamWriter resultsofRename = new StreamWriter(@"C:\Documents and Settings\jane.doe\Desktop\SharePointTesting\Results of File Rename.txt");
foreach (string files2 in paths)
try
{
string filenameOnly = Path.GetFileName(files2);
string pathOnly = Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFileName);
if (!System.IO.File.Exists(sanitized))
{
existingNames.Add(sanitized);
try
{
foreach (string names in existingNames)
{
string filename = Path.GetFileName(names);
string filepath = Path.GetDirectoryName(names);
string cleanName = regExPattern.Replace(filename, replacement_unique);
string scrubbed = Path.Combine(filepath, cleanName);
System.IO.File.Move(names, scrubbed);
//resultsofRename.Write("Path: " + pathOnly + " / " + "Old File Name: " + filenameOnly + "New File Name: " + sanitized + "\r\n" + "\r\n");
resultsofRename = File.AppendText("Path: " + filepath + " / " + "Old File Name: " + filename + "New File Name: " + scrubbed + "\r\n" + "\r\n");
}
}
catch (Exception e)
{
errors.Write(e);
}
}
else
{
System.IO.File.Move(files2, sanitized);
resultsofRename.Write("Path: " + pathOnly + " / " + "Old File Name: " + filenameOnly + "New File Name: " + sanitized + "\r\n" + "\r\n");
}
}
catch (Exception e)
{
//write to streamwriter
}
}
}
}
我在这里要做的是通过删除无效字符(在正则表达式中定义)重命名“脏”文件名,用“”替换它们。但是,我注意到如果我有重复的文件名,应用程序不会重命名它们。即如果我在同一个文件夹中有## test.txt和~~ test.txt,它们将被重命名为test.txt。所以,我创建了另一个foreach循环,用“_”代替空格替换无效字符。
问题是,无论何时我尝试运行它,都不会发生任何事情!没有任何文件被重命名!
有人能告诉我我的代码是否不正确以及如何解决?
另外 - 有人知道我怎么能每次用不同的char替换第二个foreach循环中的无效char?这样,如果有多个实例,即%Test.txt,~Test.txt和#test.txt(都要重命名为test.txt),它们可以某种方式用不同的char进行唯一命名?
答案 0 :(得分:1)
但是,您是否知道如何每次使用不同的唯一字符替换无效字符,以便每个文件名保持唯一?
这是一种方式:
char[] uniques = ",'%".ToCharArray(); // whatever chars you want
foreach (string file in files)
{
foreach (char c in uniques)
{
string replaced = regexPattern.Replace(file, c.ToString());
if (File.Exists(replaced)) continue;
// create file
}
}
您当然可以将其重构为自己的方法。另请注意,仅由唯一字符区别的文件的最大数量仅限于uniques
数组中的字符数,因此如果您有许多具有相同名称的文件,则只会根据您列出的特殊字符而有所不同,使用不同的方法可能是明智的,例如在文件名的末尾附加一个数字。
如何将数字附加到文件名的末尾(每次使用不同的#?)
Josh建议的略微修改版本可以跟踪修改后的文件名,这些文件名映射到替换后生成相同文件名的次数:
var filesCount = new Dictionary<string, int>();
string replaceSpecialCharsWith = "_"; // or "", whatever
foreach (string file in files)
{
string sanitizedPath = regexPattern.Replace(file, replaceSpecialCharsWith);
if (filesCount.ContainsKey(sanitizedPath))
{
filesCount[file]++;
}
else
{
filesCount.Add(sanitizedPath, 0);
}
string newFileName = String.Format("{0}{1}{2}",
Path.GetFileNameWithoutExtension(sanitizedPath),
filesCount[sanitizedPath] != 0
? filesCount[sanitizedPath].ToString()
: "",
Path.GetExtension(sanitizedPath));
string newFilePath = Path.Combine(Path.GetDirectoryName(sanitizedPath),
newFileName);
// create file...
}
答案 1 :(得分:1)
只是一个建议
删除/替换特殊字符后,将时间戳附加到文件名。时间戳是唯一的,因此将它们附加到文件名将为您提供唯一的文件名。
答案 2 :(得分:1)
如何维护所有重命名文件的字典,针对它检查每个文件,以及是否已经存在,在其末尾添加一个数字?
答案 3 :(得分:1)
为了回答@Josh Smeaton的回答,这里给出了一些使用字典来跟踪文件名的示例代码: -
class Program
{
private static readonly Dictionary<string,int> _fileNames = new Dictionary<string, int>();
static void Main(string[] args)
{
var fileName = GetUniqueFileName("filename.txt");
Console.WriteLine(fileName);
fileName = GetUniqueFileName("someotherfilename.txt");
Console.WriteLine(fileName);
fileName = GetUniqueFileName("filename.txt");
Console.WriteLine(fileName);
fileName = GetUniqueFileName("adifferentfilename.txt");
Console.WriteLine(fileName);
fileName = GetUniqueFileName("filename.txt");
Console.WriteLine(fileName);
fileName = GetUniqueFileName("adifferentfilename.txt");
Console.WriteLine(fileName);
Console.ReadLine();
}
private static string GetUniqueFileName(string fileName)
{
// If not already in the dictionary add it otherwise increment the counter
if (!_fileNames.ContainsKey(fileName))
_fileNames.Add(fileName, 0);
else
_fileNames[fileName] += 1;
// Now return the new name using the counter if required (0 means it's just been added)
return _fileNames[fileName].ToString().Replace("0", string.Empty) + fileName;
}
}