【发布时间】:2014-07-23 16:03:14
【问题描述】:
我觉得发布这个有点愚蠢,但这似乎是一个真正的问题,我已经把它做得足够简单,以证明它不应该失败。作为我工作的一部分,我负责维护构建系统,这些系统将文件置于版本控制之下,并将它们复制到其他位置。听起来很简单,但在尝试复制我认为已经设置为“正常”的文件时,我经常遇到文件访问冲突。
下面的代码示例只是创建了一组测试文件,将它们设为只读,然后将它们复制到另一个文件夹。如果目标文件夹中已经存在文件,则清除RO属性,以免文件复制失败。
代码工作到一定程度,但在看似随机的点尝试文件复制时会引发异常。代码都是单线程的,所以除非 .NET 在后台做一些会导致属性设置延迟的事情,否则我无法真正解释这个问题。
如果有人能解释为什么会发生这种情况,我会很感兴趣。除非我确实做错了什么,否则我不会寻找解决方案,因为我已经处理了这个问题,我只是好奇,因为似乎没有其他人报告与此相关的任何事情。
经过几次迭代,我得到了类似的东西:
“System.UnauthorizedAccessException”类型的第一次机会异常发生在 mscorlib.dll 中 附加信息:对路径“C:\TempFolderB\TEMPFILENAME8903.txt”的访问被拒绝。
另一个事实,如果您在文件复制之前获得文件属性,则结果状态表明文件属性确实正常,但检查本地文件显示为只读。
/// <summary>
/// Test copying multiple files from one folder to another while resetting RO attr
/// </summary>
static void MultiFileCopyTest()
{
/// Temp folders for our test files
string folderA = @"C:\TempFolderA";
string folderB = @"C:\TempFolderB";
/// Number of files to create
const int fileCount = 10000;
/// If the test folders do not exist populate them with some test files
if (System.IO.Directory.Exists(folderA) == false)
{
const int bufferSize = 32768;
System.IO.Directory.CreateDirectory(folderA);
System.IO.Directory.CreateDirectory(folderB);
byte[] tempBuffer = new byte[bufferSize];
/// Create a bunch of files and make them all Read Only
for (int i = 0; i < fileCount; i++)
{
string filename = folderA + "\\" + "TEMPFILENAME" + i.ToString() + ".txt";
if (System.IO.File.Exists(filename) == false)
{
System.IO.FileStream str = System.IO.File.Create(filename);
str.Write(tempBuffer, 0, bufferSize);
str.Close();
}
/// Ensure files are Read Only
System.IO.File.SetAttributes(filename, System.IO.FileAttributes.ReadOnly);
}
}
/// Number of iterations around the folders
const int maxIterations = 100;
for (int idx = 0; idx < maxIterations; idx++)
{
Console.WriteLine("Iteration {0}", idx);
/// Loop for copying all files after resetting the RO attribute
for (int i = 0; i < fileCount; i++)
{
string filenameA = folderA + "\\" + "TEMPFILENAME" + i.ToString() + ".txt";
string filenameB = folderB + "\\" + "TEMPFILENAME" + i.ToString() + ".txt";
try
{
if (System.IO.File.Exists(filenameB) == true)
{
System.IO.File.SetAttributes(filenameB, System.IO.FileAttributes.Normal);
}
System.IO.File.Copy(filenameA, filenameB, true);
}
catch (System.UnauthorizedAccessException ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
【问题讨论】:
-
查看文件夹中的文件数?根据您的文件系统类型,存在限制:superuser.com/questions/16207/…
-
对于任意数量的文件,无论大小,都会发现同样的问题,并且随机地,前几次迭代通常都很好。我的测试显示每 1,000,000 个文件大约有 23 次失败。
-
病毒扫描程序正在运行?
-
尝试禁用所有 AV / 备份软件,也在多台 PC 上尝试过,都显示完全相同的结果。
-
我也注意到了这一点,我肯定很想听听一些想法。我最终在一些项目中使用了本机 CopyFile,这并没有给我带来任何问题。