【问题标题】:Drawbacks with reading and writing a big file to or from disk at once instead of small chunks?一次从磁盘读取和写入大文件而不是小块的缺点?
【发布时间】:2011-02-12 04:16:24
【问题描述】:

我主要在基于 Windows 和 Windows CE 的系统上工作,其中 CreateFileReadFileWriteFile 是工作马,无论我是在本地 Win32 领域还是在托管的 .Net 领域。

到目前为止,我从来没有在一个块中写入或读取大文件时遇到任何明显的问题,而不是循环直到处理几个较小的块。我通常将 IO 工作委托给后台线程,当它完成时会通知我。

但是在查看文件 IO 教程或“教科书示例”时,我经常发现使用“带有小块的循环”而没有任何解释为什么使用它而不是更明显的(我敢说!)一次”。

我的做法有什么我不理解的缺点吗?

澄清:

通过大文件,我将我的单个块与多个块进行了比较。我提到的多块示例在 Windows CE 上的块大小通常为 1024 字节,而在桌面上则为 10 倍。我的大文件通常是二进制文件,例如手机中的相机照片等,大小为 2-10 MB。换句话说,不接近 1 GB。

【问题讨论】:

    标签: .net windows file winapi file-io


    【解决方案1】:

    一般来说,您不应该假设流会一次性读取所有数据。虽然对于本地文件可能是正确的,但它可能不适用于网络文件......而且它肯定不适用于一般网络流,除非更高级别已经缓冲了它们。

    然后是内存问题:假设有人要求您处理一个 3GB 的文件。如果你流它,一次处理一个块,你就没有问题。如果您尝试将整个内容读入内存,则不太可能成功...

    一般情况下:如果您可以流式传输它,那就去做。为什么要使用不太可靠且效率较低的方法?对于任何类型的鲁棒性,您仍然需要检查 Read 的返回值并将其与您期望阅读的内容进行比较...因此添加循环不会导致 非常 太多复杂性.此外,如果您发现自己经常这样做,您可能会发现可以封装到辅助方法中的模式,很可能会使用委托来表示正在处理的自定义操作。

    【讨论】:

    • @Jon:很好的答案。你的最后一段是我已经做过的事情,除了我从来没有真正看到需要深入到我的辅助方法的循环分支。另外,请参阅说明-我的大文件在常识中并不大... ;-)
    • @Johann:如果您使用的是移动设备,则 10MB 文件类似于桌面上的 10GB 文件 :) 在移动设备上不必要地占用 10MB 内存可能会导致问题 - 尽管更少所以现在肯定比几年前。
    【解决方案2】:

    这取决于您对“大”的定义。如果您只有 2 GB 的 RAM(不包括虚拟内存),那么祝您将 10 GB 的文件读入内存。

    所以,一般来说,您总是需要进行分块。这可能就是为什么教科书如此喜欢它的原因。讨论的重点只是块的大小。

    在处理流时,分块的另一个优点是内存使用率很低,并且与输入的大小无关。

    但是,如果(且仅当)您知道文件大小有一个上限,而您的 RAM 有一个下限,那么您可以一次完成所有操作。

    【讨论】:

    • @Thomas:谢谢!我通常确实有数据大小的最大可能上限,因为(请参阅说明)我的大文件在常识中并不大...... ;- )
    猜你喜欢
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 2023-04-02
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多