关闭没有Flush()的文件流

本文关键字:文件 Flush | 更新日期: 2023-09-27 18:08:08

我可以关闭一个文件流而不调用Flush(在c#中)吗?我理解CloseDispose先调用Flush方法

关闭没有Flush()的文件流

MSDN不是100%清楚,但Jon Skeet说"Flush",所以在close/dispose之前做。不会痛的,对吧?

文件流。关闭方法:

任何先前写入缓冲区的数据都被复制到之前的文件中文件流已关闭,因此没有必要在此之前调用Flush调用关闭。在调用Close之后,对文件的任何操作流可能引发异常。在Close被调用一次之后,它如果再次调用,不执行任何操作。

Dispose不清楚:

该方法通过将任何更改写入后台来处理流存储和关闭流以释放资源。

注释:评论员可能是对的,从Flush中并不是100%清楚:

在实现缓冲区的流上重写Flush。使用这种方法将任何信息从底层缓冲区移动到其目的地,清除缓冲区,或者两者都清除。根据对象的状态,你可能需要修改流中的当前位置(for)例如,如果底层流支持查找)。额外的信息见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();
}

我能说什么……所有文件都有文本-也许这只是太少的数据?

<标题> Test2 h1> 一次-每个文件都有它的字节…对我来说,它看起来像是在做我从MSDN中读到的东西:在dispose之前调用Flush或Close并不重要……对此有什么想法吗?

没有Close()/Dispose()上调用Flush(), FileStream将为您完成,您可以从其源代码:

中看到

http://referencesource.microsoft.com/mscorlib/系统/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);
        }
    }

我一直在跟踪一个新引入的错误,该错误似乎表明。net 4在处理流时不能可靠地将更改刷新到磁盘(与。net 2.0和3.5不同,它们总是可靠地这样做)。

. net 4的FileStream类在。net 4中已经进行了大量的修改,而Flush*()方法已经被重写,类似的注意似乎已经忘记了. dispose()。

这会导致文件不完整。

既然你已经说过你理解close &dispose调用flush方法,如果它没有被用户代码显式调用,我相信(通过关闭不flush)您实际上希望有可能丢弃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();
    }
}