会使用条款关闭此流? [英] Will a using clause close this stream?

查看:120
本文介绍了会使用条款关闭此流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我显然奏效自己变成一个坏习惯的编码。这是我一直在写代码的例子:

 使用(StreamReader的SR =新的StreamReader(File.Open( somefile.txt,FileMode.Open)))
{
//读取文件
}
File.Move(somefile.txt,somefile.bak); //不能移动,得到不同的是我的文件被打开



我认为这是因为使用 子句显式调用关闭()的Dispose()上在的StreamReader 的FileStream 将同时关闭。



我能解决我是有这个问题的唯一途径是通过上面块更改为此:

 使用(的FileStream FS = File.Open(somefile.txt,FileMode.Open))
{
使用(StreamReader的SR =新的StreamReader(FS))
{
//读取文件
}
}

File.Move(somefile.txt,somefile.bak); //可以没有任何错误



应该关闭的StreamReader 在第一块处理也关闭底层的FileStream ?或者,是我错了?



修改



我决定后的代码实际问题的块,就看如果我们能得到这条底线。我只是好奇吧。



我以为我有使用子句中的问题,所以我扩大了所有的东西,它仍然无法复制,每一次。我创建这个方法调用的文件,所以我不认为其他任何对文件打开的句柄。我还证实,从 Path.Combine 调用返回的字符串是正确的。

 私有静态无效GenerateFiles(列表<信用与GT;学分)
{
我的账户;
串creditFile = Path.Combine(Settings.CreditLocalPath,DateTime.Now.ToString(MMDDYY-HHMMSS)+.credits);

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

creditsFile.WriteLine(code\inc);

的foreach(在信贷信用C)
{
如果(DataAccessLayer.AccountExists(I))
{
串tpsAuth = DataAccessLayer.GetAuthCode(我。销);
creditsFile.WriteLine(的String.Format({0} {1} {\t 2:0.00},i.AuthCode,i.Pin,c.CreditAmount));
}
,否则
{
c.Error = TRUE;
c.ErrorMessage =没有户口;
}

DataAccessLayer.AddCredit(C);

}

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

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


解决方案

StreamReader.Dispose 关闭底层流(用于创建一个所有公开的方式)。然而,有一个更好的选择:

 使用(TextReader的读者= File.OpenText(file.txt的))
{
}

这有它的提示打开底层流的好处到Windows,你会按顺序访问它。



下面是一个测试应用程序,显示的第一个版本为我工作。我不是说那是什么特别的证据 - 但我很想知道它是如何为你工作。



 使用系统; 
:使用System.IO;

类节目
{
公共静态无效的主要(字串[] args)
{
的for(int i = 0; I< 1000;我++)
{使用
(StreamReader的SR =新的StreamReader
(File.Open(somefile.txt,FileMode.Open)))
{
控制台。的WriteLine(sr.ReadLine());
}
File.Move(somefile.txt,somefile.bak);
File.Move(somefile.bak,somefile.txt);
}
}
}

如果这样的作品,它表明它的是与你做什么,而阅读...



而现在这里是你的编辑问题的代码缩短的版本 - 这又正常工作对我来说,即使在网络共享。请注意,我已经改变了 FileMode.Create FileMode.CreateNew - 否则的话仍一直与旧的文件句柄的应用程序,有可能。 ?这是否对你的工作。



 使用系统; 
:使用System.IO;

公共类测试
{
静态无效的主要()
{
的StreamWriter creditsFile =新的StreamWriter(File.Open(test.txt的
FileMode.CreateNew));

creditsFile.WriteLine(code\\inc);

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

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


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 using clause explicitly called Close() and Dispose() on the StreamReader that the FileStream would be closed as well.

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 StreamReader by disposing in the first block also close the underlying FileStream? Or, was I mistaken?

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 using clause, 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.Combine calls are correct.

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

解决方案

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

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.

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.Create to FileMode.CreateNew - as otherwise there could still have been an app with a handle on the old file, potentially. Does this work for you?

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

这篇关于会使用条款关闭此流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆