Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我必须在C#中关闭()文件?_C#_.net - Fatal编程技术网

为什么我必须在C#中关闭()文件?

为什么我必须在C#中关闭()文件?,c#,.net,C#,.net,我知道这可能看起来很傻,但为什么只有在关闭()文件时,下面的代码才起作用?如果不关闭该文件,则不会写入整个流 步骤: 在表单加载时运行此代码 显示表单后,使用鼠标关闭表单 程序终止 文件对象不应该在超出范围时自动刷新或关闭吗?我是C语言的新手,但是我习惯于在C++析构函数中添加对CULL()的调用。 // Notes: complete output is about 87KB. Without Close(), it's missing about 2KB at the end. // Co

我知道这可能看起来很傻,但为什么只有在关闭()文件时,下面的代码才起作用?如果不关闭该文件,则不会写入整个流

步骤:

  • 在表单加载时运行此代码
  • 显示表单后,使用鼠标关闭表单
  • 程序终止
  • 文件对象不应该在超出范围时自动刷新或关闭吗?我是C语言的新手,但是我习惯于在C++析构函数中添加对CULL()的调用。
    // 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();
    

    因为Write()是缓冲区,而Close()会显式刷新缓冲区。

    操作系统缓存写块设备,以使操作系统具有更好的性能。将streamwriter设置为autoflush写入后,通过刷新缓冲区强制写入

    C#没有自动确定性清理功能。如果要控制清理函数的运行时间,必须确保调用该函数。使用块的
    是最常用的方法

    如果您自己没有加入cleanup调用,那么当垃圾回收器决定其他事情需要内存时,就会发生cleanup,这可能需要很长时间

    using (StreamWriter outfile = new StreamWriter("../../file.txt")) {
        outfile.Write(b64img);
    } // everything is ok, the using block calls Dispose which closes the file
    
    编辑:正如Harvey指出的,虽然收集对象时会尝试清理,但这并不能保证成功。为了避免循环引用的问题,运行时不会尝试以“正确”的顺序完成对象,因此当
    StreamWriter
    终结器运行并尝试刷新缓冲输出时,
    FileStream
    实际上可能已经死了

    如果处理需要清理的对象,请使用
    或调用
    IDisposable.Dispose
    (对于本地范围的使用)显式地进行清理。

    流是“管理”或“处理”非垃圾收集资源的对象。因此,它们(流)实现IDisposable接口,当与“using”一起使用时,该接口将确保清理非垃圾收集的资源。试试这个:

    using ( StreamWriter outfile = new StreamWriter("../../file.txt") )
    {
       outfile.Write(b64img);
    }
    
    如果没有#Close,则无法确定底层文件句柄何时会正确关闭。有时,这可能是在APP关机。

    因为C++设计人员是克隆java而不是C++,尽管名称是.< 在我看来,他们真的错过了机会。C++在范围出口上的风格破坏会更好。


    它甚至不需要释放内存,只需自动运行finalizer或IDisposable方法。

    因为您使用的是streamwriter,它在您关闭写入程序之前不会刷新缓冲区。通过将streamwriter的
    AutoFlush
    属性设置为true,可以指定希望写入程序在每次调用write时刷新

    查看文档

    如果要在不“关闭”的情况下写入文件,我将使用:

    System.IO.File
    

    或者通过显式调用Flush()。在我看来,需要关闭本机文件句柄更为重要。特别是因为这样可以锁定文件,直到最终运行终结器。仍然不会关闭文件,大多数程序都不能打开它直到第一个程序关闭它。你可能会发现讨论有助于解释C++和C++之间的差异。一般来说,我将使用C++ {析构函数(C)+ <代码> > IDISPABLE < /COD>和<代码>,使用{} < /Cord>。当然,
    使用
    比显式调用
    Close
    Dispose
    更安全,因为它将调用包装在
    try finally
    块中,以确保对象已被处理。谢谢大家,提供了清晰、快速的帮助。-1:抱怨语言有缺陷并没有真正的帮助,尤其是抱怨“C#是Java的一个副本,这就是它像Java一样工作的原因。“这是一个经过深思熟虑的设计决策,它与C#中垃圾收集的工作方式有关。请参阅以了解为什么自动处理不起作用的解释。我不是投反对票的人,但在6k rep,您现在应该知道如何留下评论了。这不是答案。顺便说一句,您想要的确实存在,它被称为C++/CLI,.NET,支持RAII并在作用域末尾自动调用析构函数。类C{Stream s;void M(){s s2=OpenAStream();this.s=s2;}}}-您的想法是,当s2超出作用域时,应该自动释放流,即使这个.s仍然有引用?你不认为这会让人们感到惊讶吗?这可能不是答案,但它加上它产生的评论信息量很大。如果C?C在中间的某个地方遇到了,当最后一个引用超出范围时,该对象如何处理?@哈维:引用计数的问题是循环引用。因此,C语言团队完全放弃了这个问题,而不是试图解决无循环参考案例。我想只有在某些时候解决这个问题才违反了“最小意外”的原则,所以我不想太强烈地反对他们的决定。事实上,如果他们只是让
    使用
    块静默地对非一次性类型不做任何事情,而不是生成编译器错误,我会非常高兴。顺便说一句,当您注意到实现了
    IDisposable
    的对象时,您应该使用
    使用
    ,除非你不想马上清理对象(例如,如果它是一个成员变量,你可能想在以后的代码< >处理/代码>)。想象一下C++必须清理所有的东西……斯卡里猜想我不知道的是,除非我关闭,否则清理功能永远不会被调用。似乎当我终止程序时,它没有对任何需要处理的对象运行清理,而是在没有垃圾收集的情况下终止。@Spooks,是的,它是。。。在C++中,有10或几年的C++是没有“删除”的。正如这个问题所示,这并不是完全没有根据的。@Harvey:在关机时,运行时会尝试调用任何剩余的终结器(在