关闭没有Flush()的文件流

时间:2011-09-11 07:43:41

标签: c# filestream flush

我可以在不调用Flush的情况下关闭文件流(在C#中)吗?我了解CloseDispose首先调用Flush方法。

7 个答案:

答案 0 :(得分:15)

MSDN并非100%明确,但Jon Skeet正在说“Flush”,所以在关闭/处置之前这样做。它不会受伤,对吧?

来自 FileStream.Close Method

  

之前写入缓冲区的任何数据都会被复制到该文件中   文件流已关闭,因此无需先调用Flush   调用Close。调用Close后,对文件执行任何操作   流可能引发异常。关闭一次后,它就被调用了   如果再次打电话,什么都不做。

处理不是那么清楚:

  

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

备注:评论员可能是正确的,并非从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

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上读到的内容:如果你在处理之前调用Flush或Close并不重要......对此有任何想法吗?

答案 1 :(得分:12)

没有Flush()上致电Close()/Dispose()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);
        }
    }

答案 2 :(得分:4)

我一直在跟踪一个新引入的错误,似乎表明.NET 4在流处理时不能可靠地刷新磁盘更改(与.NET 2.0和3.5不同,它总是可靠地执行)。

.NET 4 FileStream类已经在.NET 4中进行了重大修改,虽然Flush *()方法已被重写,但似乎已经忘记了.Dispose()。

这导致文件不完整。

答案 3 :(得分:3)

既然你已经声明你理解那个关闭&amp; dispose称为flush方法如果没有被用户代码明确调用,我相信(通过close而不刷新)你实际上希望有可能丢弃对{{ 1}},如有必要。

如果这是正确的,单独使用FileStream将无济于事。您需要将此文件加载到FileStream(或数组中,具体取决于您修改其内容的方式),然后在完成后决定是否要保存更改。

显然,问题在于文件大小。 MemoryStream使用有限大小的写缓冲区来加速操作,但一旦耗尽,就需要刷新更改。由于.NET内存限制,您只能在内存中加载较小的文件,如果您需要完全保存它们。

更简单的替代方法是制作文件的磁盘副本,并使用普通FileStream进行处理。完成后,如果您需要放弃更改,只需删除临时文件,否则用修改后的副本替换原始文件。

答案 4 :(得分:-1)

FileStream换行BufferedStream并在缓冲流之前关闭文件流。

var fs = new FileStream(...);
var bs = new BufferedStream(fs, buffersize);

bs.Write(datatosend, 0, length);

fs.Close();
try {
    bs.Close();
}
catch (IOException) {
}

答案 5 :(得分:-1)

在大循环中使用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都保存在缓冲区中,直到缓冲区为frull或程序到达sw.close()之后才会写入;

我希望这有助于理解Flush的功能

答案 6 :(得分:-2)

我认为使用简单的使用语句是安全的,该语句在调用 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();
    }
}