【问题标题】:Using file.move to rename new files in C#使用 file.move 在 C# 中重命名新文件
【发布时间】:2018-05-14 08:03:29
【问题描述】:

我对编码很陌生,我正在编写一个将重命名文件的应用程序 通过将毫秒附加到已从 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”方法中(我不确定将现有文件复制到文件夹中是否算作“创建”但是我运气不好)。

出于兴趣,如果我没有在过滤器中指定类型,我也会抛出异常,但此时此刻的紧迫性要小得多。

如果有人能提供任何我可能出错的地方,将不胜感激。

【问题讨论】:

  • FilePathField.Text.Equals(String.Empty) 会更好地表达为string.IsNullOrEmpty(FilePathField.Text)
  • fsWatcher 在范围内应该是全局的

标签: c# filesystemwatcher


【解决方案1】:

您的代码存在一些问题。

首先,你应该使用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}");
    }
}

【讨论】:

  • 感谢您的回复。你能告诉我“Console.WriteLine("[Enter] to end"); Console.ReadLine();”的意义是什么节是?是否在等待“Console.WriteLine("Done");"声明?
  • 在这里阻止控制台应用程序,直到按下 Enter 键。您可以使用 FileMon.Run() 启动控制台应用程序,将文件复制到目标目录(为了好玩,请尝试并行复制许多文件),然后按 Enter 键结束演示。如果您使用 Windows 服务、Windows 窗体或 WPF 应用程序,则不需要此功能。
猜你喜欢
  • 2017-12-14
  • 1970-01-01
  • 2014-06-25
  • 2011-03-14
  • 2022-11-25
相关资源
最近更新 更多