是否有生成复制文件的文件名的功能?

时间:2010-02-11 15:40:28

标签: c# .net copy filenames

C#是否具有为复制项目生成新名称的任何功能?
例如,如果我有一个名为“Folder”的字符串,我需要一个函数来生成一个字符串“Copy of Folder”....并且给定字符串“Copy of Folder”该函数应该产生“Copy of Folder(1) “等等......

4 个答案:

答案 0 :(得分:6)

你可以编写一个循环,如下所示:

string baseName = @"C:\Parent\Copy of Folder", actualName = baseName;
int index = 0;

while(File.Exists(actualName) || Directory.Exists(actualName))
    actualName = baseName + " (" + (++index) + ")";

根据您的用例,您应该将其放在static实用程序方法中。

答案 1 :(得分:4)

@SLaks有基本算法,但你需要记住竞争条件。 该文件可以在File.Exists检查和创建文件之间的某个时间由其他线程或进程创建。以下是基于SLak算法的解决方案概述:

FileStream fileCopy;
while(File.Exists(actualName) || Directory.Exists(acutalName))
{
  actualName = baseName + " (" + (++index) + ")"; 
  try
  {
    fileCopy = new FileStream(actualName, FileMode.CreateNew);
  }
  catch (IOException)
  {
     if (!File.Exists(actualName))
     {
       throw;
     }
  }
}

如果您无法打开文件,则可能是因为某些其他进程创建了文件或由于某些意外问题。在意外问题的情况下重新抛出异常(永远不要吞下意外的异常。)

您可以使用“new FileStream”操作是否抛出异常作为循环条件,但我避免为非错误条件抛出异常。它使得在调试器中利用“抛出抛出”异常行为变得更加困难,并且异常在计算上是昂贵的。我假设您的应用程序上下文中的错误不是文件系统上的文件与您希望用于副本的名称相同。如果我对此错了,那么如果文件存在则异常是我认为合适的。

答案 2 :(得分:0)

我从不喜欢Microsoft使用的“Copy of”前缀,因为副本不会在原件旁边排序。 Windows 7中的Microsoft现在同意我(这总是很好),因为它使用后缀而不是前缀,例如“Folder - Copy”,“Folder - Copy(2)”等。

答案 3 :(得分:0)

如果目标文件已存在,您还可以使用内置Windows功能来处理自动重命名。这样,您将获得与在资源管理器中复制文件时相同的名称。您需要的功能是SHFileOperation

简短的样本如下所示:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;

class Program
{
    static void Main(string[] args)
    {
        string file = @"C:\tmp\test.txt";
        try
        {
            SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();

            fileOp.wFunc = FO_Func.FO_COPY;
            fileOp.fFlags = (ushort)(FILEOP_FLAGS.FOF_RENAMEONCOLLISION);

            // file names need double-null termination
            fileOp.pFrom = file + '\0' + '\0';

            // use the same name as target for demo purpose
            fileOp.pTo = file + '\0' + '\0';

            int hRes = SHFileOperation(ref fileOp);
            if (hRes != 0)
            {
                throw new Win32Exception(hRes);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(ex);
        }
    }

    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
    struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        public FO_Func wFunc;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pTo;
        public ushort fFlags;
        public Int32 fAnyOperationsAborted;
        public IntPtr hNameMappings;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpszProgressTitle;
    }

    public enum FO_Func : uint
    {
        FO_MOVE = 0x0001,
        FO_COPY = 0x0002,
        FO_DELETE = 0x0003,
        FO_RENAME = 0x0004,
    }

    [Flags]
    public enum FILEOP_FLAGS : ushort
    {
        FOF_MULTIDESTFILES = 0x0001,
        FOF_CONFIRMMOUSE = 0x0002,
        FOF_SILENT = 0x0004,  
        FOF_RENAMEONCOLLISION = 0x0008,
        FOF_NOCONFIRMATION = 0x0010,  
        FOF_WANTMAPPINGHANDLE = 0x0020,  
        FOF_ALLOWUNDO = 0x0040,
        FOF_FILESONLY = 0x0080,  
        FOF_SIMPLEPROGRESS = 0x0100,  
        FOF_NOCONFIRMMKDIR = 0x0200,  
        FOF_NOERRORUI = 0x0400,  
        FOF_NOCOPYSECURITYATTRIBS = 0x0800,  
        FOF_NORECURSION = 0x1000,  
        FOF_NO_CONNECTED_ELEMENTS = 0x2000,  
        FOF_WANTNUKEWARNING = 0x4000,  
        FOF_NORECURSEREPARSE = 0x8000, 
    }
}

使用FOF_WANTMAPPINGHANDLE标志,也可以获取生成的目标文件名。有关进一步阅读和更详细的示例,请参阅CodeProject上的这篇精彩文章:

  

<强> C# does Shell, Part 2