现有文件名的问题&创建唯一文件名

时间:2010-06-30 13:18:16

标签: c#

我有这段代码:

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进行唯一命名?

4 个答案:

答案 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;            
    }
}