C# using子句是否会关闭此流?

C# using子句是否会关闭此流?,c#,filestream,dispose,streamreader,C#,Filestream,Dispose,Streamreader,我显然已经养成了一个坏的编码习惯。下面是我一直在编写的代码示例: 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子句在Str

我显然已经养成了一个坏的编码习惯。下面是我一直在编写的代码示例:

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
子句在
StreamReader
上显式调用了
Close()
Dispose()
,所以
FileStream
也会被关闭

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

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
?还是我弄错了

编辑 我决定发布一段真正有问题的代码,看看我们是否能找到问题的根源。我现在只是好奇

我想我在
使用
子句时遇到了问题,所以我扩展了所有内容,但每次都无法复制。我在这个方法调用中创建了这个文件,所以我认为其他任何东西都没有打开该文件的句柄。我还验证了从
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);
}
private静态void generateFile(列出信用)
{
账户一;
string creditFile=Path.Combine(Settings.CreditLocalPath,DateTime.Now.ToString(“MMddyy hhmmss”)+“.credits”);
StreamWriter creditsFile=新建StreamWriter(File.Open(creditFile,FileMode.Create));
creditsFile.WriteLine(“代码\公司”);
foreach(学分c中的学分)
{
if(DataAccessLayer.AccountExists(i))
{
字符串tpsAuth=DataAccessLayer.GetAuthCode(i.Pin);
creditsFile.WriteLine(String.Format(“{0}{1}\t{2:0.00}”,i.AuthCode,i.Pin,c.CreditAmount));
}
其他的
{
c、 错误=真;
c、 ErrorMessage=“无账户”;
}
DataAccessLayer.AddCredit(c);
}
creditsFile.Close();
creditsFile.Dispose();
字符串dest=Path.Combine(Settings.CreditArchivePath,Path.GetFileName(creditFile));
文件移动(creditFile,dest);
//文件。删除(错误文件);
}

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

using (TextReader reader = File.OpenText("file.txt"))
{
}
这还有一个额外的好处,即它打开底层流,并向Windows提示您将按顺序访问它

这里有一个测试应用程序,它显示了第一个版本对我有效。我不想说这是什么特别的证据,但我很想知道它对你有多有效

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

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

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

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

是否有可能其他文件锁定了somefile.txt

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

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


或者,您可以获取更多详细信息,并检查您的应用程序是否正常发布。

我会尝试使用
FileInfo.Open()
FileInfo.MoveTo()
而不是
File.Open()
File.Move(
)。您还可以尝试使用
FileInfo.OpenText()
。但这些只是建议。

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

  • 在创建文件时扫描文件的客户端或服务器上的病毒扫描程序
  • Windows有在网络共享上搞砸事情的习惯。我记得这主要是多个具有平面文件数据库的读/写客户机的问题,但肯定可以解释您的问题
  • 窗户。我不确定这在Win2K中是否仍然是一个问题,但FileMon会告诉您

  • 编辑:如果您可以在服务器机器的act中捕获它,那么Sysinternal的句柄将告诉您它打开了什么

    知道我为什么不能在第一个区块移动文件吗?不,应该没问题。奇怪。第一个版本总是失败,第二个版本总是有效吗?刚刚尝试了第一个版本,在一个循环中对我有效了20次。我用第一种方式编码了100次,以前从来没有出现过问题。现在,我正在windows共享上打开该文件,这是解决该问题的唯一方法。第一个例子每次都失败了,第二个例子每次都成功了。所以我认为我做得不对。有没有可能其他应用程序打开并锁定了该文件?你也可以检查一下。
    DateTime.Now.ToString(“MMddyy hhmmss”)
    你每秒创建多少个文件?@Dave,每天一个。此函数一天只调用一次。请检查防病毒扫描程序、索引服务器等。我认为,从另一个角度看,它看起来更好。请理解,这与任何其他具有初始子句、后跟语句的构造(其中语句可以是块)没有什么不同。(一个典型的例子是
    if(list!=null)foreach(列表中的对象项){…}
    ,它是嵌套在
    if
    中的
    foreach
    ),具体来说,这是“嵌套”——也是一种非理想的缩进样式,因为它不指示嵌套。如果缩进除第一行以外的所有行,则会更清楚发生了什么:第二个“使用”嵌套在第一行中。我将尝试FileInfo方法,但我认为在下面,它们只是对File.MoveYep的调用,但可能它们在内部处理流(由FileInfo.Open()创建)。另外,文档中说他们只做了一次安全检查,所以可能会稍微快一点……非常有趣。我过去在另一个没有编写代码的应用程序中也遇到过问题,但我们发现罪魁祸首是AVG。我必须对此进行调查。
    using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
    using(StreamReader sr = new StreamReader(fs))
    {
        //read file
    }
    
    net files