【问题标题】:File.Copy() copying corrupt file in multithreaded C# programFile.Copy() 在多线程 C# 程序中复制损坏的文件
【发布时间】:2017-02-27 09:18:08
【问题描述】:

我的程序中有两个线程。 一个线程一直在观察 USB 事件(USB 插入或移除)。

第二个线程(文件复制线程)持续监控第一个线程设置的 USB 插入标志。插入 USB 后,文件复制线程开始将 Pdf 文件从 PC 复制到 USB。

USB 移除后,USB 监控线程将isUSBInsterted 标志设置为False,文件复制线程应该停止文件传输。

问题:只有当文件复制线程已经在传输 Pdf 文件但 USB 已经弹出时才会出现问题。在这种情况下,在 USB 中创建了一个损坏的 Pdf 文件,然后即使我尝试删除该文件,文件也会再次出现(还有其他问题,例如无法覆盖等)

问题:如何确保File.Copy() 不会在 USB 中创建损坏的文件。我认为即使程序不是多线程的,也会出现问题,因为这与开始将文件复制到 USB 和 USB 在复制过程进行的那一刻弹出有关。

我的复制代码:

    private bool CopyFile(string FilenameToBeCopied, string SrcDirectory, string DstDirectory)
    {
        bool CopiedSuccessfully = false;
        try
        {
            Directory.CreateDirectory(DstDirectory); //This will create a directory if it does not exist yet.
            File.Copy(SrcDirectory + "/" + FilenameToBeCopied, DstDirectory + "/" + FilenameToBeCopied, true);
            Console.WriteLine("Copied: " + FilenameToBeCopied);
            CopiedSuccessfully = true;
        }
        catch (IOException copyError)
        {
            Console.WriteLine(copyError.Message);
        }
        return CopiedSuccessfully;
    }

【问题讨论】:

  • 我认为您对此无能为力。您不应该在写入存储设备时删除它们,因为这可能会导致文件损坏(正如您所发现的那样)。
  • File.Copy 在这种情况下不会为您提供任何弹性。您可能不得不尽可能地打开文件流并跨缓冲区复制,当您收到未插入设备的事件时,请记住您在文件流中的位置并将其关闭。这将留下部分文件,但当设备再次插入时,您可以恢复该文件。
  • @AdamHouldsworth 即使您一次写入一个缓冲区,如果您在中途退出设备,最终可能会导致文件损坏。当然,如果您弹出设备,对 Stream.Write() 的调用可能会抛出 IOException。此时,没有要“关闭”的文件流。
  • @MatthewWatson 是的,你可以,我不否认。我猜,弹性将来自容差。就我个人而言,我会做的是将文件完全装箱,或者回溯到您知道已写入的缓冲区 - 例如从您收到事件时起减去 2 秒。但是,这些都不是微不足道的或保证的 - 唯一的选择是将写入事件的任何文件合并,或者如果事件非常接近最后写入的文件 - 也考虑合并它。在复制结束时,可以进行哈希验证,并且可以删除任何失败的文件。
  • 我认为一种可能性是检查要复制的文件的确切大小->如果缓冲区的大小等于要复制的文件的大小,则将文件复制到缓冲区->复制然后复制文件…………有意义吗?

标签: c# multithreading


【解决方案1】:

这是预期结果

如果我理解您的问题,您正在写入存储介质,并且在执行此操作时将其删除。这就像要求数据损坏一样。

编辑:

这显然是由不知道如何操作计算机的用户造成的,虽然它会发生,但我不会在这上面浪费太多时间。我会用另一种方式解决这个问题,而不是尝试恢复损坏的数据。

  1. 向用户提供有关正在发生的事情的明确消息,以便他们可以识别正在进行的复制操作,并且现在移除 USB 驱动器会导致问题。
  2. 通知用户操作已结束,可以安全地移除 USB 驱动器。
  3. 您将能够检测 USB 驱动器是否在复制过程运行时被移除,通知用户并要求他们重新插入。
  4. 如果发生第 3 步,请检查您是否能够覆盖,您永远不会知道。如果它不起作用,请稍微更改带有后缀的文件名并将其与该文件名一起写入 USB 驱动器。这样用户在任何情况下都能得到他需要的东西,即使他搞砸了。
  5. 如果文件名很重要,并且后缀不是一个选项,您甚至可以尝试使用通用 UUID 作为文件名写入文件,并在进程成功完成后将文件重命名为其源文件名,这样任何损坏的文件不会成为问题,在这些情况下不需要后缀。

如果存在这种可能性,您可能需要检查在这种情况下是否可以选择格式化驱动器。它可能会解决您的问题,并且可能对用户来说是一个小问题。

【讨论】:

  • 这就是我无法覆盖损坏文件的问题。当我尝试覆盖损坏的文件时,我会收到一个期望,说 The file or directory is corrupted and unreadable.
  • @r41n 如果幸运的话,您可以删除 USB 驱动器上现有的损坏文件。但最有可能的是,您要么需要运行 chkdsk.exe 并希望它能够修复 U 盘上损坏的文件系统,要么您必须重新格式化 U 盘。除此之外,您可以在 USB 记忆棒上使用 NTFS 而不是 FAT,NTFS 对损坏的恢复能力要强一些。
  • @nos:谢谢,我尝试运行CHKDSK 并删除了损坏的文件。现在,我打算制定一个逻辑来检查目录中是否有任何损坏的文件,如果有则运行CHKDSK
  • @nos,我知道。如果我是 OP,我可能会寻找一种完成工作的方法,一种让我的应用程序交付的方法。每次用户 f**ks up 时运行 chkdsk 或格式化驱动器可能是不可取的。预防胜于治疗。
猜你喜欢
  • 2011-06-10
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2012-08-02
  • 2015-06-17
  • 1970-01-01
  • 2020-02-04
  • 2014-03-03
相关资源
最近更新 更多