C# 文件移动和覆盖

发布于 2024-12-25 10:07:23 字数 744 浏览 4 评论 0原文

我正在开发一个多线程应用程序。我的代码中有一处:

File.Delete(sidetapedata);
File.Move(sidetapedata2, sidetapedata); //sidetapedata and sidetapedata2 are two file paths that correspond to sidetapedata.txt and sidetaptdata2.txt in some directory.

第二行有时运行良好,有时会抛出 IOException :

Cannot create a file when that file already exists.

还有一个线程正在访问 sidetapedata 文件,但那个线程只读取该文件,没有写入操作。我使用锁来保护竞争条件。不知道为什么会发生这种情况。

更新:即使 Visual C# 调试器向我显示此异常,查看包含这些文件的目录,我发现没有 sidetapedata.txt文件,但有一个 sidetapedata2.txt 文件!

UPDATE2:此外,仅当 sidetapedata.txtsidetapedata2.txt 均为空白时才会发生此行为

I'm developing a multi threaded application. I have somewhere in my code :

File.Delete(sidetapedata);
File.Move(sidetapedata2, sidetapedata); //sidetapedata and sidetapedata2 are two file paths that correspond to sidetapedata.txt and sidetaptdata2.txt in some directory.

The second line sometimes runs fine and other times, it throws an IOException :

Cannot create a file when that file already exists.

There is one more thread that is accessing the sidetapedata file but that one is only reading this file, no write operations. I am using locks to protect race conditions. Don't know why this is happening.

UPDATE : even when visual c# debugger shows me this exception, looking into the directory that contains these files, I see there is no sidetapedata.txt file but there is a sidetapedata2.txt file!

UPDATE2 : Also, this behavior only happens when sidetapedata.txt and sidetapedata2.txt are both blank

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

↘人皮目录ツ 2025-01-01 10:07:23

不知道为什么会发生这种情况,除非 Delete 调用在文件系统中触发了某些事件,这意味着直到调用返回后不久,它才实际上被删除。有几个选项:

  • 您可以循环(在出错之前使用某种最大循环数),在尝试移动之前检查文件是否存在,如果删除后文件仍然存在,则短暂睡眠
  • 您可以使用 File.Copy( sidetapedata, sidetapedata2, true) 来复制而不是移动,然后删除源文件。但这会降低效率,假设移动将通过简单的文件系统目录条目更改来处理(而不是真正复制数据)
  • 您可以在目标文件上使用 File.Move 而不是 File.Delete 将其移动到某个无害的其他文件名,然后将其删除,希望 MoveDelete 更原子。

我怀疑线程在这里无关紧要 - 我建议您编写一个简短但完整的程序来验证这一点,以便您可以排除它(并轻松测试解决方法)。

Not sure why this would happen unless there's some event triggered in the file system by the Delete call which means it's not actually deleted until slightly after the call returns. A few options:

  • You could loop (with some sort of maximum number of loops before erroring) where you check for the file's existence before trying the move, and sleep briefly if it still exists after deletion
  • You could use File.Copy(sidetapedata, sidetapedata2, true) to copy instead of moving, and then delete the source file. This will be less efficient though, assuming the move would be handled by a simple file system directory entry change (rather than really copying the data)
  • You could use File.Move on the target file instead of File.Delete to move it to some harmless other filename, then delete that afterwards, hoping that the Move is more atomic than the Delete.

I suspect the threading is irrelevant here - I suggest you write a short but complete program to validate that, so you can rule it out (and easily test the workarounds).

以为你会在 2025-01-01 10:07:23

我不确定这对于 .NET 是否相同,但根据 win32 DeleteFile API参考:

DeleteFile 函数将文件标记为在关闭时删除。因此,直到文件的最后一个句柄关闭后才会发生文件删除。

因此,在调用Delete 返回和Windows 关闭文件的最后一个句柄之间可能存在一个时间窗口。看来你是在这段时间打电话给Move的。

I am unsure if this is the same for .NET, but according to the win32 DeleteFile api reference:

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed.

So there is probably a window of time between the call to Delete returning and Windows closing the last handle to the file. It looks like you are calling Move during this period of time.

做个ˇ局外人 2025-01-01 10:07:23

在.NET Core 3.0及更高版本中,您可以调用Move(String, String, Boolean)并将参数overwrite设置为true,这将替换文件(如果存在)。

请参阅 https://learn .microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.0

In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.

see https://learn.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.0

最丧也最甜 2025-01-01 10:07:23

根据这个答案:使用FileStream文件共享

FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);

As per this answer : use FileStream with FileShare

FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文