在 C# 中使用 file.move 重命名新文件

Using file.move to rename new files in C#

我对编码很陌生,我正在编写一个将重命名文件的应用程序 通过将毫秒附加到已从 MFD 扫描的文件的现有文件名。 该文件夹为共享文件夹,重命名的文件应保留在其中,不能复制到其他地方。

通过大量搜索,我知道 File.Move 是我前进的方向,但是,我似乎无法让它发挥作用。

这是我的代码:

private void MonitorToggle_Click(object sender, EventArgs e)
    {
       // Create a new FileSystemWatcher object.
        FileSystemWatcher fsWatcher = new FileSystemWatcher();

        switch (MonitorToggle.Text)
        {
            // Start Monitoring…
            case startMonitoring:
                if (!FilePathField.Text.Equals(String.Empty))
                {
                    //Set the watched folder path equal to the file path variable
                    fsWatcher.Path = FilePathField.Text;

                    // Set Filter.
                    fsWatcher.Filter = (FileTypeField.Text.Equals(String.Empty))? "*.*" : FileTypeField.Text;

                    // Monitor files and subdirectories.
                    fsWatcher.IncludeSubdirectories = true;

                    // Monitor all changes specified in the NotifyFilters.
                    fsWatcher.NotifyFilter = NotifyFilters.LastWrite;

                    fsWatcher.EnableRaisingEvents = true;

                    // Raise Event handlers.
                    fsWatcher.Changed += new FileSystemEventHandler(OnChanged);
                    fsWatcher.Created += new FileSystemEventHandler(OnCreated);
                }
                else
                {
                    MessageBox.Show("Please select a folder to monitor.", "Warning",MessageBoxButtons.OK, MessageBoxIcon.Warning );
                }
                break;

            // Stop Monitoring…
            case stopMonitoring:
            default:

                fsWatcher.EnableRaisingEvents = false;
                fsWatcher = null;
                break;
        }

    }

    public void OnChanged (object sender, FileSystemEventArgs e)
    {
        FileInfo file = new FileInfo(e.Name);
        string dateStamp = DateTime.Now.ToString("fff");
        string fName = file.Name;
        string newFile = string.Concat(fName, dateStamp);
        File.Move(fName,newFile);            
    }

    public void OnCreated(object sender, FileSystemEventArgs e)
    {
        FileInfo file = new FileInfo(e.Name);
        string dateStamp = DateTime.Now.ToString("fff");
        string fName = file.Name;
        string newFile = string.Concat(fName, dateStamp);
        File.Move(fName, newFile);
    }

    private void BrowseButton_Click(object sender, EventArgs e)
    {
        // Create FolderBrowserDialog object.
        FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
        // Show a button to create a new folder.
        folderBrowserDialog.ShowNewFolderButton = true;
        DialogResult dialogResult = folderBrowserDialog.ShowDialog();
        // Get selected path from FolderBrowserDialog control.
        if (dialogResult == DialogResult.OK)
        {
            FilePathField.Text = folderBrowserDialog.SelectedPath;
            Environment.SpecialFolder root = folderBrowserDialog.RootFolder;
        }
    }

每当我在我正在观看的文件夹中创建一个新文件时,它什么都不做。一开始我以为可能是因为我只有"OnCreated"方法,所以我把它复制到"OnChanged"方法中(我不确定将现有文件复制到文件夹中是否算作"created" 但我运气不好。

出于兴趣,如果我没有在过滤器中指定类型,我也会抛出一个异常,但目前这并不那么紧迫。

如果有人能指出我可能出错的地方,将不胜感激。

您的代码存在一些问题。

首先,您应该使用e.FullPath而不是e.Name,否则代码将尝试重命名当前目录中的文件,而不是监视目录中的文件。

其次,要接收 Created 事件,您应该包含 NotifyFilters.FileName.

但是,这对您没有多大帮助,因为在复制文件之前,文件在创建和更改事件中被锁定,因此您会得到一个异常。此外,您可能会收到不止一个 Changed 事件(在我的测试中,无论文件大小如何,我总是收到两个,但在 Windows 或 .Net 框架的不同版本上可能会有所不同)。

要解决此问题,您可以使用计时器或线程来完成任务。这是一个使用 ThreadPool 线程的示例。每当 created 被触发时,您都会创建一个新线程。在线程中检查文件是否被锁定(尝试打开文件),当文件被解锁时,进行重命名。

public class FileMon
{
    public static void Run()
    {
        FileSystemWatcher fsWatcher = new FileSystemWatcher();
        fsWatcher.Path = @"C:\Test\";        
        fsWatcher.Filter = "*.*" ;
        fsWatcher.IncludeSubdirectories = true;

        // Monitor all changes specified in the NotifyFilters.
        fsWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName ;

        fsWatcher.EnableRaisingEvents = true;

        // Raise Event handlers.
        fsWatcher.Changed += OnChanged;
        fsWatcher.Created += OnCreated;
        Console.WriteLine("[Enter] to end"); Console.ReadLine();
        fsWatcher.EnableRaisingEvents = false;
    }

    static void Worker(object state)
    {
        FileSystemEventArgs fsArgs = state as FileSystemEventArgs;
        bool done = false;
        FileInfo fi = new FileInfo(fsArgs.FullPath);

        do
        {
            try
            {
                using (File.Open(fsArgs.FullPath, FileMode.Open))
                {
                    done = true;
                }
            }
            catch
            {
                done = false;
            }
            Thread.Sleep(1000);
        } while (!done);
        Console.WriteLine("DOne");
        string dateStamp = DateTime.Now.ToString("fff");
        string fName = fi.FullName;
        string newFile = fsArgs.FullPath + dateStamp;
        File.Move(fsArgs.FullPath, newFile);
    }

    private static void OnCreated(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"Created {e.ChangeType} : {e.Name}");
        ThreadPool.QueueUserWorkItem(Worker, e);
    }

    static void OnChanged(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"{e.ChangeType} : {e.FullPath}");
    }
}