File.Move()重命名不起作用

时间:2010-06-30 20:03:36

标签: c#

我的应用程序采用“不干净”的文件名并“清理”它们。 “Unclean”文件名包含@,#,〜,+,%等字符。“清理”过程用“”替换这些字符。但是,我发现如果同一个文件夹中有两个文件,在清理后会有相同的名称,我的应用程序不会重命名任何一个文件。 (即清洁后,## test.txt和~test.txt都将命名为test.txt)。

因此,我放入一个循环,基本上检查我的应用程序试图重命名的文件名是否已存在于该文件夹中。但是,我尝试运行它,它不会重命名所有文件。我做错了吗?

这是我的代码:

        public void FileCleanup(List<string> paths)
    {
        string regPattern = (@"[~#&!%+{}]+");
        string replacement = "";

        Regex regExPattern = new Regex(regPattern);
        List<string> existingNames = new List<string>();
        StreamWriter errors = new StreamWriter(@"C:\Documents and Settings\joe.schmoe\Desktop\SharePointTesting\Errors.txt");
        StreamWriter resultsofRename = new StreamWriter(@"C:\Documents and Settings\joe.schmoe\Desktop\SharePointTesting\Results of File Rename.txt");

        var filesCount = new Dictionary<string, int>();
        string replaceSpecialCharsWith = "_";

        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))
                {
                    System.IO.File.Move(files2, sanitized);
                    resultsofRename.Write("Path: " + pathOnly + " / " + "Old File Name: " + filenameOnly + "New File Name: " + sanitized + "\r\n" + "\r\n");   
                }

                else 
                {
                    existingNames.Add(sanitized);
                    foreach (string names in existingNames)
                    {

                        string sanitizedPath = regExPattern.Replace(names, replaceSpecialCharsWith);
                        if (filesCount.ContainsKey(sanitizedPath))
                        {
                            filesCount[names]++;
                        }
                        else
                        {
                            filesCount.Add(sanitizedPath, 1);
                        }

                        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);
                        System.IO.File.Move(names, newFileName);

                    }
                 }
              }
            catch (Exception e)
            {
                //write to streamwriter

            }

    }

}

任何人都知道为什么我的代码不会唯一地重命名重复文件?

3 个答案:

答案 0 :(得分:3)

  • 您执行foreach (string names in existingNames),但existingNames为空。
  • 你的if (System.IO.File.Exists(sanitized))向后:如果文件不存在,它会组成一个新名称,而不是存在。
  • 您创建了一个字符串newFileName,但仍使用sanitizedPath代替newFileName进行重命名。
  • filesCount.Add(sanitizedPath, 0)的第二个参数应为1或2.毕竟,您遇到了第二个同名文件。
  • 如果filesCount[sanitizedPath]等于0,则根本不更改文件名,因此您将覆盖现有文件。

答案 1 :(得分:2)

除了Sjoerd指出的问题之外,您似乎正在检查文件是否存在以及确实存在您是否移动它。你的if语句应该是

     if (!System.IO.File.Exists(sanitized))
     {
         ...
     }    
     else 
     {
         foreach (string names in existingNames)
             {
                 ...    
             }
         }
     }

更新

我同意您应该将代码拆分为更小的方法。它将帮助您确定哪些部件正在工作,哪些部件不工作。话虽这么说,我会摆脱现有的名单。因为你有filesCount字典,所以不需要它。你的else子句看起来像这样:

     if (filesCount.ContainsKey(sanitized))
     {
         filesCount[sanitized]++;
     }
     else
     {
       filesCount.Add(sanitized, 1);
     }

     string newFileName = String.Format("{0}{1}.{2}", 
                                        Path.GetFileNameWithoutExtension(sanitized),
                                        filesCount[sanitized].ToString(),
                                        Path.GetExtension(sanitized));

     string newFilePath = Path.Combine(Path.GetDirectoryName(sanitized), newFileName);
     System.IO.File.Move(files2, newFileName);

请注意,我更改了String.Format方法调用。你有一些逗号和空格在那里看起来不正确的构建路径,虽然我可能会在你的实现中遗漏一些东西。此外,在Move中,我将第一个参数从“names”更改为“files2”。

答案 2 :(得分:2)

使代码更简洁的一个好方法是将它作为逻辑块拆分为方法。

FindUniqueName(string filePath, string fileName);
该方法会在fileName前面添加一个字符,直到fileName对filePath唯一。

MoveFile(string filePath, string from, string to);
如果文件已经存在,该方法将使用FindUniqueName方法。

以这种方式测试清理会更容易。

另外,您应该检查文件是否需要重命名

if (String.Compare(sanitizedFileName, filenameOnly, true) != 0)
  MoveFile(pathOnly, fileNameOnly, sanitizedFileName);

private string FindUniqueName(string fileDirectory, string from, string to)
{
    string fileName = to;

    // There most likely won't be that many files with the same name to reach max filename length.
    while (File.Exists(Path.Combine(fileDirectory, fileName)))
    {
        fileName = "_" + fileName;
    }

    return fileName;
}

private void MoveFile(string fileDirectory, string from, string to)
{
    to = FindUniqueName(fileDirectory, from, to);

    File.Move(Path.Combine(fileDirectory, from), Path.Combine(fileDirectory, to));
}