1

使用以下代码,我读取了一个文件并保持流打开。

    static void Main(string[] args)
    {
        FileStream fileStream = new FileStream(@"C:\temp\test1.txt", FileMode.Open);
        Console.ReadLine();
    }

如果我现在尝试重命名此文件,则会显示消息“文件正在使用”。 正在使用的文件

看起来应该可以重命名文件(在操作系统级别),即使它正在使用中:为什么重命名加载的 .net 程序集有效?

.net 将文件加载到流中时,为什么不能重命名文件?

4

2 回答 2

2

关于程序集,.NET 应该使用类似的方式打开程序集FileShare.ReadWrite,即使它已加载到域中,任何其他进程都可以写入或重命名整个文件。

AFAIK,.NET 没有FileShare用于允许或禁止重命名文件共享的托管枚举值(类似于FileShare.Rename),但 Win32 应该具有因此程序集加载将创建带有掩码的文件流FileShare.ReadWrite | FileShare.RenameFileShare.Delete包括重命名但也删除整个文件...)。

为了证明这一点,我尝试了以下代码:

    FileStream a = File.Open(@"C:\blah.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    a.Dispose();

在打开文件流并处理它之前,我无法删除整个文件,但我可以重命名它。

请注意,程序集会AppDomain在需要时加载到其中,这意味着您可能可以编写、删除或重命名程序集,因为它尚未加载。

尝试删除已经加载到的程序集AppDomain:你不能(我刚刚尝试过,测试代码在控制台应用程序中运行,我无法在运行时删除可执行文件)。现在尝试重命名它:它可以工作。

概括

这完全是关于如何打开文件以及打开文件流时使用了哪个文件掩码配置:这就是为什么您的文件无法重命名但您可以重命名已加载的程序集的原因

像下一个一样修改您的代码,您将能够重命名整个文件(甚至删除它!):

    FileStream fileStream = File.Open(@"C:\temp\test1.txt", FileMode.Open, FileShare.ReadWrite | FileShare.Delete);
    Console.ReadLine();
于 2013-02-08T16:09:03.613 回答
1

创建时FileStream不会将其数据加载到内存中。当您在寻找流时,文件内容仍然是从磁盘中读取的——当您需要读取大文件时这是一件好事。

如果您只想将整个内容加载到您可以使用的内存中File.ReadAllBytes。您可以在此处阅读更多相关信息:http: //msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx

注意:如果要使用流而不是字节数组,可以使用MemoryStream并将读取的文件内容传递给它。

于 2013-02-08T15:52:01.450 回答