当前位置:  开发笔记 > 编程语言 > 正文

using子句会关闭此流吗?

如何解决《using子句会关闭此流吗?》经验,为你挑选了2个好方法。

我显然已经习惯了一个糟糕的编码习惯.这是我写的代码示例:

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

我认为,因为using条款明确要求Close(),并Dispose()StreamReaderFileStream会也关闭.

我能解决问题的唯一方法是将上面的块更改为:

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

应该StreamReader通过在第一个区块中关闭而关闭底层FileStream?或者,我错了吗?

编辑

我决定发布实际的违规代码块,看看我们是否可以深入了解这一点.我现在很好奇.

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

private static void GenerateFiles(List 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);
}

Jon Skeet.. 39

是的,StreamReader.Dispose关闭基础流(用于创建一个的所有公共方式).但是,有一个更好的选择:

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

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

这是一个测试应用程序,显示第一个版本适合我.我并不想说这是任何特别的证据 - 但我很想知道它对你有多好.

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");
        }
    }
}

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

现在这里是您编辑的问题代码的缩短版本 - 即使在网络共享上,这也适用于我.请注意,我已更改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");
    }
}


Not Sure.. 11

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

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

在这种情况下处理的顺序仍然与嵌套块相同(即,在这种情况下,StreamReader仍将在FileStream之前部署).



1> Jon Skeet..:

是的,StreamReader.Dispose关闭基础流(用于创建一个的所有公共方式).但是,有一个更好的选择:

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

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

这是一个测试应用程序,显示第一个版本适合我.我并不想说这是任何特别的证据 - 但我很想知道它对你有多好.

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");
        }
    }
}

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

现在这里是您编辑的问题代码的缩短版本 - 即使在网络共享上,这也适用于我.请注意,我已更改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");
    }
}



2> Not Sure..:

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

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

在这种情况下处理的顺序仍然与嵌套块相同(即,在这种情况下,StreamReader仍将在FileStream之前部署).


对我来说,它看起来更好.
理解这与任何其他具有initial子句的构造没有什么不同,后面跟一个语句,其中语句可以是一个块.(一个典型的例子是`if(list!= null)foreach(列表中的对象项){...}`,它是嵌入在`if`中的`foreach`.)具体来说,这*是*"嵌套" - 以及非理想的缩进样式,因为它不表示嵌套.如果缩进除第一行以外的所有行,则更清楚的是:第二行"使用"嵌套在第一行中.
推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有