关闭文件而不使用 using
我有一个类,它从一个文件流读取数据并写入另一个文件流。我担心在 closeFiles() 中处理完成后关闭流。
您将如何处理一个流的处置可能引发异常以阻止调用另一流的处置的可能性?
我应该关闭并在流中进行处理还是只处理一个?
如果我从流处理中发现任何错误,然后继续移动和删除文件(如 lastOperation() 中所示),会发生什么情况?
在完美的世界中,我想在 C++ 样式初始化列表中使用 using 语句,但我很确定这在 C# 中是不可能的。
编辑:感谢大家的快速回复。所以我应该做的是从 IDisposable 派生,然后更改构造函数并添加两个这样的处理方法?:
~FileProcessor()
{
Dispose(true);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
sw.Flush();
}
closeFiles();
disposed = true;
}
}
这基本上就是我正在做的事情:
class FileProcessor
{
private string in_filename;
private string out_filename;
private StreamReader sr;
private StreamWriter sw;
bool filesOpen = false;
public FileProcessor(string filename)
{
in_filename = filename;
out_filename = filename + ".out";
openFiles();
}
~FileProcessor()
{
closeFiles();
}
private void openFiles()
{
sr = new StreamReader(in_filename);
sw = new StreamWriter(out_filename);
filesOpen = true;
}
private void closeFiles()
{
if (filesOpen)
{
sr.Close();
sw.Close();
sr.Dispose();
sw.Dispose();
filesOpen = false;
}
}
/* various functions to read, process and write to the files */
public void lastOperation()
{
closeFiles();
File.Delete( in_filename );
Directory.Move(out_filename, outdir + out_filename);
}
}
I have a class which reads data from one file stream and writes to another. I am concerned about closing the streams after the processing has finished in closeFiles().
How would you handle the possibility that the dispose of one stream may throw an exception stopping the dispose of the other stream from being called.?
Should I be calling close and dispose on the streams or just one?
What happens if I catch any errors from the stream disposes and then continue with moving and deleting of the files as shown in lastOperation()?
In a perfect world I'd like to use a using statement in a c++ style initialisation list but I'm pretty sure that's not possible in c#.
EDIT : thanks for the quick responses guys. So what I should be doing is deriving from IDisposable and then change the constructor and add the two disposing methods like this?:
~FileProcessor()
{
Dispose(true);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
sw.Flush();
}
closeFiles();
disposed = true;
}
}
This is basically what I'm doing:
class FileProcessor
{
private string in_filename;
private string out_filename;
private StreamReader sr;
private StreamWriter sw;
bool filesOpen = false;
public FileProcessor(string filename)
{
in_filename = filename;
out_filename = filename + ".out";
openFiles();
}
~FileProcessor()
{
closeFiles();
}
private void openFiles()
{
sr = new StreamReader(in_filename);
sw = new StreamWriter(out_filename);
filesOpen = true;
}
private void closeFiles()
{
if (filesOpen)
{
sr.Close();
sw.Close();
sr.Dispose();
sw.Dispose();
filesOpen = false;
}
}
/* various functions to read, process and write to the files */
public void lastOperation()
{
closeFiles();
File.Delete( in_filename );
Directory.Move(out_filename, outdir + out_filename);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的 FileProcessor 类不应该有析构函数。虽然没有什么用,但是很贵。
它应该有一个
Dispose()
(并实现 IDisposable 接口)来调用 closeFiles()。就像@marcelo 回答的那样, Stream.Dispose() 不应该抛出。您可以依靠它来学习 BCL 课程。
但是您应该检查每个 Reader/Writer 是否为 null,以防第一个打开但第二个失败:
您的
filesOpen
无法覆盖两者。Your FileProcessor class should not have a destructor. It is of no use but it is expensive.
It should have a
Dispose()
(and implement the IDisposable interface) to call closeFiles().And like @marcelo answered, Stream.Dispose() should not throw. You can rely on this for BCL classes.
But you should check each Reader/Writer for null, in case the first one opened but the second one failed:
Your
filesOpen
can't cover both.我认为如果您在类中使用 IDisposable 对象,那么让您的类实现 IDisposable 接口是一个很好的做法。
然后,您应该确保在
Dispose()
实现中不会引发异常。如果您处置的每件物品都能保证这一点,那么您的客户就会安全。I think it is a good practise to have your class implements
IDisposable
interface if you are using IDisposable object inside it.Then, you should make sure that, in your
Dispose()
implementation, don't throw exceptions. If every object you dispose makes this guarantee, your client will be safe.Dispose 方法永远不应该抛出异常。甚至还有一个代码分析工具警告。
Dispose methods should never throw exceptions. There's even a code analysis tool warning for this.
在 C# 中,
using
确实存在。提供给 using 语句的对象必须实现 IDisposable 接口。该接口提供了 Dispose 方法,该方法应该释放对象的资源。如果您的 StreamReader 和 StreamWriter 实现了 IDisposable,您可以将它们放在 using 块中,当您使用完它们后,它们将被干净地处理掉。
In C#,
using
does exist. The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object's resources.If your StreamReader and StreamWriter implement IDisposable, you can put them in a using block, and they will be disposed of cleanly when you have finished with them.