C# .NET文件访问冲突

C# .NET文件访问冲突,c#,.net,C#,.net,我觉得发布这篇文章有点愚蠢,但这似乎是一个真正的问题,我已经做得足够简单,以证明它不应该失败。作为我工作的一部分,我负责维护在版本控制下获取文件并将其复制到其他位置的构建系统。听起来很简单,但当我试图复制我认为已经设置为“正常”的文件时,我经常遇到文件访问冲突 下面的代码示例只是创建一组测试文件,将其设置为只读,然后将其复制到另一个文件夹中。如果目标文件夹中已存在文件,则清除“RO”属性,以便文件复制不会失败 代码工作到一定程度,但在尝试复制文件时,在看似随机的点上会引发异常。代码都是单线程的,

我觉得发布这篇文章有点愚蠢,但这似乎是一个真正的问题,我已经做得足够简单,以证明它不应该失败。作为我工作的一部分,我负责维护在版本控制下获取文件并将其复制到其他位置的构建系统。听起来很简单,但当我试图复制我认为已经设置为“正常”的文件时,我经常遇到文件访问冲突

下面的代码示例只是创建一组测试文件,将其设置为只读,然后将其复制到另一个文件夹中。如果目标文件夹中已存在文件,则清除“RO”属性,以便文件复制不会失败

代码工作到一定程度,但在尝试复制文件时,在看似随机的点上会引发异常。代码都是单线程的,所以除非.NET在幕后做了一些导致属性设置延迟的事情,否则我无法真正解释这个问题

如果有人能解释为什么会这样,我会感兴趣的。我不是在寻找解决方案,除非我确实做错了什么,因为我已经处理了这个问题,我只是好奇,因为似乎没有其他人报告过与此相关的任何事情

经过几次迭代后,我得到如下结果:

mscorlib.dll中发生类型为“System.UnauthorizedAccessException”的首次意外异常 其他信息:对路径“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);
                }
            }
        }
    }
//
///重置RO attr时,测试将多个文件从一个文件夹复制到另一个文件夹
/// 
静态无效多文件复制测试()
{
///测试文件的临时文件夹
字符串folderA=@“C:\TempFolderA”;
字符串folderB=@“C:\TempFolderB”;
///要创建的文件数
const int fileCount=10000;
///如果测试文件夹不存在,请使用一些测试文件填充它们
if(System.IO.Directory.Exists(folderA)==false)
{
const int bufferSize=32768;
System.IO.Directory.CreateDirectory(folderA);
System.IO.Directory.CreateDirectory(folderB);
byte[]tempBuffer=新字节[bufferSize];
///创建一组文件并使它们都为只读
for(int i=0;i
在该方法的文档中,我发现了以下内容:

例外情况:
系统。未授权异常

path
指定了一个只读文件。
-或-当前平台不支持此操作。
-或-调用方没有所需的权限

因此,如果我不得不猜测,目标中的文件(例如,
filenameB
)实际上已经存在。它被标记为只读,因此,根据上面的文档引发异常

相反,您需要做的是通过反向位掩码删除只读属性:

if (FileExists(filenameB))
{
    // Remove the read-only attribute
    FileAttributes attributes = File.GetAttributes(filenameB);
    attributes &= ~FileAttributes.ReadOnly;
    File.SetAttributes(filenameB, attributes);

    // You can't OR the Normal attribute with other attributes--see MSDN.
    File.SetAttributes(filenameB, FileAttributes.Normal);
}
平心而论,
SetAttributes
方法的文档并不清楚在文件标记为
Readonly
后如何设置文件属性。当然,这里有一个例子(使用
Hidden
属性),但他们没有明确指出需要使用反转位掩码来删除
Hidden
Readonly
属性。人们可以很容易地假设这正是他们选择“取消设置”属性的方式。文档中也不清楚会发生什么,例如,如果您将文件标记为:

File.SetAttributes(pathToFile, FileAttributes.Normal);
File.SetAttributes(pathToFile, FileAttributes.Archived);
这是否会导致文件首先设置了
Normal
属性,然后只设置了
Archived
,还是会导致文件设置了
Normal
属性,然后再设置
Archived`属性,从而生成一个正常但已存档的文件?我相信是前者,而不是后者,基于如何使用反转位掩码从文件中“删除”属性

如果有人发现任何相反的情况,请发表评论,我会相应地更新我的答案

HTH.

(这不是一个完整的答案,但我没有足够的代表性