我知道这可能看起来很愚蠢,但为什么以下代码只有在我关闭()文件时才有效?如果我不关闭文件,则不会写入整个流。
步骤:
文件对象超出范围时是不是应该自动刷新或关闭?我是C#的新手,但我习惯在C ++析构函数中添加对Close()的调用。
// Notes: complete output is about 87KB. Without Close(), it's missing about 2KB at the end.
// Convert to png and then convert that into a base64 encoded string.
string b64img = ImageToBase64(img, ImageFormat.Png);
// Save the base64 image to a text file for more testing and external validation.
StreamWriter outfile = new StreamWriter("../../file.txt");
outfile.Write(b64img);
// If we don't close the file, windows will not write it all to disk. No idea why
// that would be.
outfile.Close();
答案 0 :(得分:22)
C#没有自动确定性清理。如果要控制运行时,必须确保调用清理功能。 using
块是执行此操作的最常见方式。
如果你没有自己进行清理调用,那么当垃圾收集器决定其他东西需要内存时,就会发生清理,这可能需要很长时间。
using (StreamWriter outfile = new StreamWriter("../../file.txt")) {
outfile.Write(b64img);
} // everything is ok, the using block calls Dispose which closes the file
编辑:正如哈维指出的那样,虽然在收集对象时会尝试进行清理,但这并不能保证成功。为了避免循环引用的问题,运行时不会尝试以“正确”的顺序最终确定对象,因此FileStream
终结器运行并尝试刷新缓冲时StreamWriter
实际上已经死了输出
如果您处理需要清理的对象,请使用using
(对于本地范围的用法)或通过调用IDisposable.Dispose
(对于长期存在的对象,例如类成员的指示对象)进行显式处理)。
答案 1 :(得分:8)
因为Write()被缓冲并且缓冲区被Close()显式刷新。
答案 2 :(得分:3)
Streams是“管理”或“处理”非垃圾回收资源的对象。因此,它们(Streams)实现了IDisposable接口,当与'using'一起使用时,将确保清理非垃圾收集的资源。试试这个:
using ( StreamWriter outfile = new StreamWriter("../../file.txt") )
{
outfile.Write(b64img);
}
如果没有#Close,您无法确定何时正确关闭基础文件句柄。有时,这可以在应用程序关闭。
答案 3 :(得分:2)
因为您正在使用一个流写器,并且在您Close()
编写器之前它不会刷新缓冲区。通过将streamwriter的AutoFlush
属性设置为true,可以指定希望编写器在每次调用write时进行刷新。
查看文档。 http://msdn.microsoft.com/en-us/library/system.io.streamwriter.aspx
如果你想写一个没有“关闭”的文件,我会用:
System.IO.File
答案 4 :(得分:1)
操作系统缓存写入块设备以使操作系统具有更好的性能。在将写入器设置为autoflush后,通过刷新缓冲区强制写入。
答案 5 :(得分:-2)
因为C#设计师在克服Java而不是C ++,尽管名称不同。
在我看来,他们真的错过了这条船。 。
它甚至不必释放内存更好,只需自动运行终结器或IDisposable方法。