sco*_*ttm 30 c# dispose filestream 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
Run Code Online (Sandbox Code Playgroud)
我认为,因为using条款明确要求Close(),并Dispose()在StreamReader该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
Run Code Online (Sandbox Code Playgroud)
应该StreamReader通过在第一个区块中关闭而关闭底层FileStream?或者,我错了吗?
我决定发布实际的违规代码块,看看我们是否可以深入了解这一点.我现在很好奇.
我以为我在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);
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 39
是的,StreamReader.Dispose关闭基础流(用于创建一个的所有公共方式).但是,有一个更好的选择:
using (TextReader reader = File.OpenText("file.txt"))
{
}
Run Code Online (Sandbox Code Playgroud)
这有一个额外的好处,它打开底层流,并提示您将按顺序访问它.
这是一个测试应用程序,显示第一个版本适合我.我并不想说这是任何特别的证据 - 但我很想知道它对你有多好.
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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果有效,它表明这与你在阅读时所做的事情有关...
现在这里是您编辑的问题代码的缩短版本 - 即使在网络共享上,这也适用于我.请注意,我已更改FileMode.Create为FileMode.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");
}
}
Run Code Online (Sandbox Code Playgroud)
Not*_*ure 11
注意 - 您的使用块不需要嵌套在它们自己的块中 - 它们可以是顺序的,如:
using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
using(StreamReader sr = new StreamReader(fs))
{
//read file
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下处理的顺序仍然与嵌套块相同(即,在这种情况下,StreamReader仍将在FileStream之前部署).