【问题标题】:Avoiding the use of temporary files, when the function wants a FILE * passed当函数想要传递 FILE * 时,避免使用临时文件
【发布时间】:2011-10-13 06:41:07
【问题描述】:

我目前使用 C++ 使用 boost::graph 进行一些与图形相关的计算。 boost::graph 可以将其图形输出为点文件,我使用 std::stringstream 来捕获输出点文件。因此点文件的内容驻留在内存中。

我想使用点文件来可视化图形(尽可能快)。因此,我想生成点文件,生成 svg 文件并将其打印到某个画布上。我想避免为此使用临时文件,因为图形应该很小并且内存仍然可用。

然而,graphviz libgraph 只有函数extern Agraph_t *agread(FILE *);,我能想到的唯一方法是在文件句柄struct __FILE 中进行修改,这真的是不可移植的。

在 Unix/linux 中,如何让库将内存内容作为文件读取?

我刚刚发现来自 GraphViz 的 libcgraph 允许在此处输入重载版本,但到目前为止,文档并没有为我指出一些有用的地方。

【问题讨论】:

    标签: c graphviz boost-graph


    【解决方案1】:

    嗯,这可以说是 API 中的一个错误,但这里有一个想法。这是假设agread() 函数会将文件作为二进制数据读入。

    请注意,我不熟悉您正在使用的 API,但我希望这仍然有用。

    1. 使用mmap() 将文件映射到内存中。
    2. 使用该内存区域来构建图形。
    3. 当需要调用 agread() 时,将该文件描述符打开到 FILE * 结构中(fopen()fdopen(),如果您没有关闭描述符)。
    4. 传递FILE * 结构。

    编辑:或者,忽略我的回答并使用fmemopen() 呼叫。这可能正是您所需要的。不过,我不想删除我的答案,以防有人正在写回复:-)。

    【讨论】:

    • 这并不能避免将文件写入磁盘,我真的在这里尝试这样做。
    • 假设您正在按照我的原始答案说话,它很可能会避免写入磁盘。您提到图表很小,这大大增加了操作系统仅缓存写入而不实际写入磁盘的机会。您必须调用 msync() 才能刷新到磁盘。
    • 嗯,可能是真的。但是如果程序终止会发生什么。我必须再次删除这些文件,或者将它们放在 tmp 文件夹中。 fmemopen() 是一个 glibc 函数。不幸的是,代码也需要在 freebsd 上运行。
    • 好点。您可以像在另一个答案中提到的 Ilmari Karonen 一样使用 tmpfile(),也可以像我在修改后的答案中提到的那样使用 fmemopen(),它根本不需要文件。编辑:啊,我看到了 fmemopen 的问题。
    【解决方案2】:

    您可以使用pipe() 创建一个管道,将数据写入输入端并使用fdopen() 将输出文件描述符转换为适合传递给agread() 的文件句柄。

    但是,这只有在您确定数据is less than PIPE_BUF bytes 的情况下才有效;否则写入可能会永远阻塞,因为另一端没有读取任何内容。

    一般来说,使用临时文件更容易也更可靠。只需使用tmpfile() 获取文件句柄,将数据写入其中,倒带并将其传递给agread()

    fh = tmpfile();
    fputs( data, fh );
    rewind( fh );
    graph = agread( fh );
    fclose( fh );
    

    (当然,你应该检查错误,为了简洁,我没有这样做。)

    【讨论】:

      【解决方案3】:

      如果您愿意使用 GNU libc 扩展,您可以将 C 字符串打开为 FILE*;文档位于http://www.gnu.org/s/libc/manual/html_node/String-Streams.html

      【讨论】:

        【解决方案4】:

        在 Windows 上,您可以使用 fopen 打开命名管道。

        FILE* f = fopen("\\\\.\\Pipe\\<pipe name>", "rb");
        

        因此,您可以在单独的线程中创建一个管道,在其中推送数据,agread 将从该管道中读取数据,而无需临时文件。

        【讨论】:

        • 我不在windows环境中。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多