C# using 子句会关闭这个流吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/707336/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 14:12:29  来源:igfitidea点击:

Will a using clause close this stream?

c#filestreamdisposestreamreader

提问by scottm

I've apparently worked myself into a bad coding habit. Here is an example of the code I've been writing:

我显然已经使自己养成了不良的编码习惯。这是我一直在编写的代码示例:

using(StreamReader sr = new StreamReader(File.Open("somefile.txt", FileMode.Open)))
{
    //read file
}
File.Move("somefile.txt", "somefile.bak"); //can't move, get exception that I the file is open

I thought that because the usingclause explicitly called Close()and Dispose()on the StreamReaderthat the FileStreamwould be closed as well.

我认为,因为using条款明确要求Close(),并Dispose()StreamReaderFileStream将被关闭为好。

The only way I could fix the problem I was having was by changing the above block to this:

我可以解决我遇到的问题的唯一方法是将上面的块更改为:

using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
{
  using(StreamReader sr = new StreamReader(fs))
  {
    //read file
  }
}

File.Move("somefile.txt", "somefile.bak"); // can move file with no errors

Should closing the StreamReaderby disposing in the first block also close the underlying FileStream? Or, was I mistaken?

StreamReader通过在第一个块中处理来关闭是否也应该关闭底层FileStream?或者,我错了?

Edit

编辑

I decided to post the actual offending block of code, to see if we can get to the bottom of this. I am just curious now.

我决定发布实际有问题的代码块,看看我们是否可以深入了解它。我现在只是好奇。

I thought I had a problem in the usingclause, so I expanded everything out, and it still can't copy, every time. I create the file in this method call, so I don't think anything else has a handle open on the file. I've also verified that the strings returned from the Path.Combinecalls are correct.

我以为我的using条款有问题,所以我将所有内容都展开了,但它仍然无法复制,每次都无法复制。我在这个方法调用中创建了文件,所以我认为没有其他任何东西在文件上打开了句柄。我还验证了Path.Combine调用返回的字符串是正确的。

private static void GenerateFiles(List<Credit> credits)
{
    Account i;
    string creditFile = Path.Combine(Settings.CreditLocalPath, DateTime.Now.ToString("MMddyy-hhmmss") + ".credits");

    StreamWriter creditsFile = new StreamWriter(File.Open(creditFile, FileMode.Create));

    creditsFile.WriteLine("code\inc");

    foreach (Credit c in credits)
    {
        if (DataAccessLayer.AccountExists(i))
        {
            string tpsAuth = DataAccessLayer.GetAuthCode(i.Pin);
            creditsFile.WriteLine(String.Format("{0}{1}\t{2:0.00}", i.AuthCode, i.Pin, c.CreditAmount));
        }
        else
        {
            c.Error = true;
            c.ErrorMessage = "NO ACCOUNT";
        }

        DataAccessLayer.AddCredit(c);

    }

    creditsFile.Close();
    creditsFile.Dispose();

    string dest =  Path.Combine(Settings.CreditArchivePath, Path.GetFileName(creditFile));
    File.Move(creditFile,dest);
    //File.Delete(errorFile);
}

采纳答案by Jon Skeet

Yes, StreamReader.Disposecloses the underlying stream (for all public ways of creating one). However, there's a nicer alternative:

是的,StreamReader.Dispose关闭底层流(对于创建一个的所有公共方式)。但是,还有一个更好的选择:

using (TextReader reader = File.OpenText("file.txt"))
{
}

This has the added benefit that it opens the underlying stream with a hint to Windows that you'll be accessing it sequentially.

这有一个额外的好处,它打开底层流,并提示 Windows 您将按顺序访问它。

Here's a test app which shows the first version working for me. I'm not trying to say that's proof of anything in particular - but I'd love to know how well it works for you.

这是一个测试应用程序,它显示了对我有用的第一个版本。我并不是想说这证明了任何特别的东西 - 但我很想知道它对你的效果如何。

using System;
using System.IO;

class Program
{
    public static void Main(string[] args)
    {
        for (int i=0; i < 1000; i++)
        {
            using(StreamReader sr = new StreamReader
                  (File.Open("somefile.txt", FileMode.Open)))
            {
                Console.WriteLine(sr.ReadLine());
            }
            File.Move("somefile.txt", "somefile.bak");
            File.Move("somefile.bak", "somefile.txt");
        }
    }
}

If that works, it suggests that it's something to do with what you do while reading...

如果这有效,则表明这与您在阅读时所做的事情有关......

And now here's a shortened version of your edited question code - which again works fine for me, even on a network share. Note that I've changed FileMode.Createto FileMode.CreateNew- as otherwise there couldstill have been an app with a handle on the old file, potentially. Does this work for you?

现在这是您编辑过的问题代码的缩短版本 - 即使在网络共享上,它对我来说也很好用。请注意,我已更改FileMode.CreateFileMode.CreateNew- 否则可能仍然存在具有旧文件句柄的应用程序。这对你有用吗?

using System;
using System.IO;

public class Test
{    
    static void Main()
    {
        StreamWriter creditsFile = new StreamWriter(File.Open("test.txt", 
                                          FileMode.CreateNew));

        creditsFile.WriteLine("code\inc");

        creditsFile.Close();
        creditsFile.Dispose();

        File.Move("test.txt", "test2.txt");
    }
}

回答by Not Sure

Note - your using blocks do not need to be nested in their own blocks - they can be sequential, as in:

注意 - 您的 using 块不需要嵌套在它们自己的块中 - 它们可以是顺序的,如下所示:

using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
using(StreamReader sr = new StreamReader(fs))
{
    //read file
}

The order of disposal in this case is still the same as the nested blocks (ie, the StreamReader will still dispose before the FileStream in this case).

这种情况下的处置顺序仍然与嵌套块相同(即,在这种情况下,StreamReader 仍将在 FileStream 之前进行处置)。

回答by Zhaph - Ben Duguid

Is there any possibility that something else has a lock to somefile.txt?

是否有其他东西锁定 somefile.txt 的可能性?

A simple check from a local (to the file) cmd line

从本地(到文件)cmd 行的简单检查

net files

may well give you some clues if anything else has a lock.

如果其他东西有锁,可能会给你一些线索。

Alternatively you can get something like FileMonto take even more details, and check that your app is releasing properly.

或者,您可以使用FileMon 之类的工具来获取更多详细信息,并检查您的应用程序是否正确发布。

回答by MartinStettner

I would try to use FileInfo.Open()and FileInfo.MoveTo()instead of File.Open()and File.Move(). You could also try to use FileInfo.OpenText(). But these are just suggestions.

我会尝试使用FileInfo.Open()andFileInfo.MoveTo()代替File.Open()and File.Move()。您也可以尝试使用FileInfo.OpenText(). 但这些只是建议。

回答by Mark Brackett

Since this doesn't seem to be a coding issue, I'm going to put my syadmin hat on and offer a few suggestions.

由于这似乎不是编码问题,因此我将戴上我的 syadmin 帽子并提供一些建议。

  1. Virus scanner on either the client or server that's scanning the file as it's created.
  2. Windows opportunistic lockinghas a habit of screwing things up on network shares. I recall it being mostly an issue with multiple read/write clients with flat file databases, but cachingcould certainly explain your problem.
  3. Windows file open cache. I'm not sure if this is still a problem in Win2K or not, but FileMon would tell you.
  1. 在创建文件时扫描文件的客户端或服务器上的病毒扫描程序。
  2. Windows机会锁定有把网络共享搞砸的习惯。我记得这主要是具有平面文件数据库的多个读/写客户端的问题,但缓存肯定可以解释您的问题。
  3. Windows文件打开缓存。我不确定这在 Win2K 中是否仍然存在问题,但 FileMon 会告诉你。

Edit: If you can catch it in the act from the server machine, then Sysinternal's Handle will tell you what has it open.

编辑:如果您可以在服务器机器上捕获它,那么 Sysinternal 的 Handle 会告诉您它打开了什么。