【问题标题】:Write simultaneousely to two streams同时写入两个流
【发布时间】:2010-11-05 20:07:35
【问题描述】:

有没有办法将两个流(或文件描述符)耦合在一起,以便写入一个流也会写入第二个流? (C,Linux)

谢谢。

【问题讨论】:

    标签: c linux io stream


    【解决方案1】:

    使用funopenfwopen 并提供您自己的写入函数来写入多个FILE*s。

    例子:

    FILE *files[2] = ...;
    
    FILE *f = fwopen((void *)files, my_writefn);
    
    // ... use f as you like ...
    
    int my_writefn(void *cookie, const char *data, int n) {
      FILE **files = (FILE **)cookie;
      fwrite(data, n, 1, files[0]);
      return fwrite(data, n, 1, files[1]);
    }
    

    (省略错误处理。)

    请注意,funopenfwopen 是 BSD,而不是标准 Linux。我不知道是否有与 Linux 兼容的等价物。

    【讨论】:

    • 显然,没有。它们不在手册页中(至少在我的系统上)。
    • funopen 在 BSD 和 Mac OS X 上。在 Linux 上使用 fopencookie。
    • @mark4o:感谢您提供的信息。 @Jack:似乎使用 fopencookie() 的实现会非常相似。没有在这里更新我的答案,但你应该有一些前进的方向。
    • 这样可以节省计算机时间。我不确定它是否可以节省程序员的时间。不过,巧妙的技巧(即使不是完全可移植的,其中可移植=“在 unices 之间”)。
    【解决方案2】:

    我首先想到的也是“tee”。所以,让我们将 C 和 shell 与 popen 结合起来:

    FILE * multi_out;
    
    multi_out = popen( "tee file1.out > file2.out", "w");
    /* error checks, actual work here */
    pclose( multi_out);
    /* error checks here */
    

    作为一个 Unix 顽固分子,我假设你不会在 Windows 上尝试这个。

    【讨论】:

    【解决方案3】:

    用户 laalto 是正确的,但在 Linux 上,您要查找的函数称为 fopencookie。更正 laalto 的 Linux 示例会导致:

    int my_writefn(void *cookie, const char *data, int n) {
      FILE **files = (FILE **)cookie;
      fwrite(data, n, 1, files[0]);
      return fwrite(data, n, 1, files[1]);
    }
    
    int noop(void) { return 0; }
    cookie_io_functions_t my_fns = {
      (void*) noop,
      (void*) my_writefn,
      (void*) noop,
      (void*) noop
    };
    
    FILE *files[2] = ...;
    
    FILE *f = fopencookie((void *)files, "w", my_fns);
    
    // ... use f as you like ...
    

    当您写入f 时,系统将执行您的my_writefn 函数,将传递给fwrite 的数据传递给它。为了使事情更容易,您可能还希望将文件流的缓冲更改为面向行:

    setvbuf(f, NULL, _IOLBF, 0);
    

    这将缓冲传递给fwrite 的数据,直到输出换行符或从附加到进程的任何流(例如标准输入)中读取任何数据。 注意:您必须在fopencookie 之后但在任何数据写入流之前调用sevbuf

    我使用行缓冲,因为我通常使用fopencookie 将 stderr 重定向到 syslog 或通过网络套接字,并且处理面向行的数据更容易和更有效。

    【讨论】:

      【解决方案4】:

      不确定是不是你想要的,但 unix 中的 'tee' 有类似的功能。

      【讨论】:

      • 所以“C++”这个家伙被改装了,但你却因为建议“建立在他人的工作之上”而被改装。这不对……
      【解决方案5】:

      您可以使用boost::iostreams 实现类似于tee 的功能。

      【讨论】:

      • 你有 C 的例子吗?因为那是严格的 C++ ;)
      猜你喜欢
      • 2014-03-13
      • 1970-01-01
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 2019-03-04
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      相关资源
      最近更新 更多