你不需要在调用Close()/Dispose()
时调用Flush()
,如你从源代码中可以看到的一样,FileStream
会为你自动执行:
http://referencesource.microsoft.com/#mscorlib/system/io/filestream.cs,e23a38af5d11ddd3
[System.Security.SecuritySafeCritical] // auto-generated
protected override void Dispose(bool disposing)
{
// Nothing will be done differently based on whether we are
// disposing vs. finalizing. This is taking advantage of the
// weak ordering between normal finalizable objects & critical
// finalizable objects, which I included in the SafeHandle
// design for FileStream, which would often "just work" when
// finalized.
try {
if (_handle != null && !_handle.IsClosed) {
// Flush data to disk iff we were writing. After
// thinking about this, we also don't need to flush
// our read position, regardless of whether the handle
// was exposed to the user. They probably would NOT
// want us to do this.
if (_writePos > 0) {
FlushWrite(!disposing); // <- Note this
}
}
}
finally {
if (_handle != null && !_handle.IsClosed)
_handle.Dispose();
_canRead = false;
_canWrite = false;
_canSeek = false;
// Don't set the buffer to null, to avoid a NullReferenceException
// when users have a race condition in their code (ie, they call
// Close when calling another method on Stream like Read).
//_buffer = null;
base.Dispose(disposing);
}
}
MSDN的文档并不是100%清楚,但Jon Skeet建议在关闭/释放之前使用"Flush"方法。这样做不会有任何坏处,对吧?
在关闭文件流之前将缓冲区中先前写入的任何数据复制到文件中,因此在调用Close之前不需要调用Flush。在调用Close一次后,对文件流的任何操作都可能引发异常。如果再次调用Close,则不会执行任何操作。
Dispose的说明并不是很清晰:
通过将更改写入后备存储器并关闭流以释放资源来处理该流。
注:评论者可能是正确的,从Flush的说明并不是100%清楚:
在实现缓冲区的流上重写Flush。使用此方法将底层缓冲区中的任何信息移动到其目的地,清除缓冲区或两者皆可。根据对象的状态,您可能必须修改流中的当前位置(例如,如果底层流支持寻址)。有关详细信息,请参见CanSeek。
当使用StreamWriter或BinaryWriter类时,请勿刷新基础流对象。相反,请使用该类的Flush或Close方法,该方法确保首先将数据刷新到底层流,然后写入文件。
var textBytes = Encoding.ASCII.GetBytes("Test123");
using (var fileTest = System.IO.File.Open(@"c:\temp\fileNoCloseNoFlush.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes,0,textBytes.Length);
}
using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseNoFlush.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes, 0, textBytes.Length);
fileTest.Close();
}
using (var fileTest = System.IO.File.Open(@"c:\temp\fileFlushNoClose.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes, 0, textBytes.Length);
fileTest.Flush();
}
using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseAndFlush.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes, 0, textBytes.Length);
fileTest.Flush();
fileTest.Close();
}
我该说什么呢...所有的文件都有这段文本-也许这只是数据太少了?
var rnd = new Random();
var size = 1024*1024*10;
var randomBytes = new byte[size];
rnd.NextBytes(randomBytes);
using (var fileTest = System.IO.File.Open(@"c:\temp\fileNoCloseNoFlush.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
}
using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseNoFlush.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
fileTest.Close();
}
using (var fileTest = System.IO.File.Open(@"c:\temp\fileFlushNoClose.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
fileTest.Flush();
}
using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseAndFlush.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
fileTest.Flush();
fileTest.Close();
}
再说一遍-每个文件都有它的字节...在我看来,它看起来像是在做我从MSDN上读到的事情:无论你在dispose之前调用Flush或Close都没关系...对此有什么想法吗?
Close()
而不调用Flush()
,但是你不能在不刷新的情况下关闭 :) - Jon Skeet既然你已经明白了如果用户代码没有显式调用flush方法,close和dispose会自动调用它,那么我认为(通过不调用flush的close),你实际上想有一个可能性来丢弃对FileStream
所做的更改,如果必要的话。
如果是这样的话,仅使用FileStream
是不够的。您需要将此文件加载到MemoryStream
(或数组中,具体取决于您如何修改其内容)中,然后在完成后决定是否要保存更改。
问题在于文件大小,显然。 FileStream
使用有限大小的写入缓冲区以加快操作速度,但一旦它们被耗尽,就需要刷新更改。由于.NET内存限制,如果需要完全保存文件,则只能在内存中加载较小的文件。
一个更简单的替代方案是创建文件的磁盘副本,并使用普通的FileStream
进行操作。完成后,如果需要丢弃更改,只需删除临时文件;否则,用修改后的副本替换原始文件。
将FileStream
包装在BufferedStream
中,并在缓冲流之前关闭文件流。
var fs = new FileStream(...);
var bs = new BufferedStream(fs, buffersize);
bs.Write(datatosend, 0, length);
fs.Close();
try {
bs.Close();
}
catch (IOException) {
}
在大循环中使用Flush()是值得的。当你需要在一个循环内读写一个大文件时,这样做是有意义的。否则,如果缓冲区或计算机足够大,则在关闭之前不进行Flush()也没有关系。
例如:你需要读取一个大文件(以一种格式)并将其写入.txt文件中。
StreamWriter sw = .... // using StreamWriter
// you read the File ...
// and now you want to write each line for this big File using WriteLine ();
for ( .....) // this is a big Loop because the File is big and has many Lines
{
sw.WriteLine ( *whatever i read* ); //we write here somrewhere ex. one .txt anywhere
sw.Flush(); // each time the sw.flush() is called, the sw.WriteLine is executed
}
sw.Close();
在这里非常重要的是使用Flush(); 因为否则每个writeLine都保存在缓冲区中,直到缓冲区满或程序达到sw.close();才会写入。
我希望这有助于更好地理解Flush的功能。
我认为使用简单的using语句是安全的,在调用GetBytes()后会关闭流;
public static byte[] GetBytes(string fileName)
{
byte[] buffer = new byte[4096];
using (FileStream fs = new FileStream(fileName))
using (MemoryStream ms = new MemoryStream())
{
fs.BlockCopy(ms, buffer, 4096); // extension method for the Stream class
fs.Close();
return ms.ToByteArray();
}
}
Close
函数? - Jon Skeet