繁体   English   中英

使用 setvbuf 写入文件,有条件地丢弃缓冲区内容

[英]Writing to file using setvbuf, conditionally discard buffer contents

我想写一个简单的 API

  1. 允许用户打开文件。
  2. 让用户将数据写入文件
  3. 跟踪写入调用并在每次写入调用后检查写入的数据。
  4. 如果数据无效,则防止数据被写入磁盘 -> discard(file)

作为起点,我编写了下面的测试程序,它使用fopensetvbuf以完全缓冲的“rb+”模式打开一个文件。 stream 在完全缓冲模式下打开,原因如下:

http://www.cplusplus.com/reference/cstdio/setvbuf/

mode 指定文件缓冲的模式。

三个特殊的宏常量 [...]:

_IOFBF 完全缓冲:在 output 上,一旦缓冲区已满(或刷新),就会写入数据。 在输入上,当请求输入操作并且缓冲区为空时,缓冲区被填充。

我的测试程序包含可以放置有效性检查以及应该丢弃缓冲区内容的注释。

我的问题是如何完成discard(file)操作,这意味着删除无效缓冲区内容的步骤?

这背后的想法是在缓冲区中组装一些数据,在每次或多次写入操作后进行定期有效性检查,如果数据有效,则仅将数据写入磁盘。 因此,如果有效性检查失败,我将需要丢弃缓冲区。 当有效性检查通过时,应将整个缓冲区内容写入文件。

我的代码草稿如下所示。 这是一个简化的例子:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int main(void)
{
    static uint8_t buffer[10000];
    
    /* The following would be part of mylib_init */
    FILE *file = fopen("test", "wb+");
    
    if (file == NULL){
        print ("open error!");
        exit(-1);
    }
    
    if ( 0 != setvbuf(file , buffer, _IOFBF , sizeof(buffer) ) ){
        print("Could not set buffer!");
        fclose(file);
        exit (-2);
    }
    
    /* The following would be part of mylib_write_data.
       Each write and check resembles one func call */

    // Pretend the user writes some data into the file
    // ...
    // fwrite(x)
    
    if (data_in_buffer_not_valid(buffer)){
       discard(file);
    }

    // ...
    // fwrite(y)
    //

    if (data_in_buffer_not_valid(buffer)){
       discard(file);
    }

    // ...
    // fwrite(z)
    // ...
    
         
    // The following would be part of mylib_exit
    // Cleanup stuff
    fclose(file)

    return 0;
}

如果您想要一些像“临时”这样的临时文件,您想将数据写入其中然后稍后检索它们,那么移植接口将是tmpfile() - 它是为此创建的接口。 写入该文件,如果需要,可以rewind ,当你准备好时, rewind它并从它逐块读取到另一个文件。

在 linux 上,您可以使用fmemopenfopencookie通过FILE*写入缓冲区 - 这些功能在 windows 上不可用。

我也强烈考虑创建您自己的接口,将结果存储在 memory 中。 编写类似struct mystream; mystream_init(struct mystream *); mystream_printf(struct mystream *, const char *fmt, ...); struct mystream; mystream_init(struct mystream *); mystream_printf(struct mystream *, const char *fmt, ...); 等是您有时在fopencookie不可用时在 C 中执行的一些任务。 并考虑编写用于存储数据的接口,以便您实际上调用 function 而不是调用fwrite ,它将检查数据并写入它们并一路处理它们。

至于setvbuf ,请注意标准。 C11 7.21.3p3 开始

当 stream 未缓冲时,字符应尽快从源或目标出现。 否则,字符可能会作为一个块被累积并传输到主机环境或从主机环境传输。 当 stream 完全缓冲时,[...]。 当 stream 被行缓冲时,[...]对这些特性的支持是实现定义的,并且可能会受到 setbuf 和 setvbuf 函数的影响。

而且这些缓冲模式可能根本不被支持 C11 7.21.5.6 开始

The setvbuf function may be used only after the stream pointed to by stream has been associated with an open file and before any other operation (other than an unsuccessful call to setvbuf) is performed on the stream. [...]数组的内容在任何时候都是不确定的

您不能指望缓冲区的内容。 不要期望那里有任何数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM