使用C语言.我有一个写入标准输出的函数.
我想捕获该输出,稍微修改一下(替换一些字符串).然后再次将其输出到标准输出.所以我想开始:
char huge_string_buf[MASSIVE_SIZE];freopen("NUL", "a", 标准输出);-或- freopen("/dev/null", "a", stdout);setbuf(标准输出,巨大的字符串缓冲区);/* 修改巨大的字符串缓冲区 */
现在的问题是,如何将巨大的字符串缓冲区输出回原来的标准输出?
一个想法是模仿标准 Unix 实用程序 tee
的功能,但要完全在您的程序中这样做,而不依赖于外部重定向.
所以我写了一个简单的函数,mytee()
,它似乎可以工作.它使用 shmget()、pipe()、fork() 和 dup2()
:
#include #include #include #include 静态字符 *mytee(整数大小){int shmid = shmget(IPC_PRIVATE, size + 1, 0660 | IPC_CREAT);int pipe_fds[2];管道(pipe_fds);开关(叉()){case -1://= 错误错误(叉");退出(EXIT_FAILURE);案例 0: {//= 孩子char *out = shmat(shmid, 0, 0), c;int i = 0;出[0] = 0;dup2(pipe_fds[0], 0);//将管道重定向到孩子的标准输入setvbuf(stdout, 0, _IONBF, 0);while (read(0, &c, 1) == 1 && i ", c);//将父级的标准输出传递给真正的标准输出,出[i++] = c;//然后在 mycapture 缓冲区中缓冲出[i] = 0;//(额外的 <> 只是为了清楚起见)}_退出(退出_成功);}默认值://= 父级dup2(pipe_fds[1], 1);//用输出替换 stdout 到 childsetvbuf(stdout, 0, _IONBF, 0);返回 shmat(shmid, 0, 0);//返回孩子的捕获缓冲区}}
我的测试程序是:
int main(void) {char *mycapture = mytee(100);//捕获前 100 个字节printf("你好世界");//示例测试字符串睡眠(1);fprintf(stderr, "\nCaptured: \n", mycapture);返回0;}
输出为:
要在您的应用程序中使用它,在 mytee()
中,您需要将测试语句 printf("<%c>", c)
替换为只需 write(1, &c, 1)
.并且您可能需要在对 read
的调用中处理信号.在两个 dup2()
之后,您可能需要添加:
close(pipe_fds[0]);关闭(pipe_fds[1]);
有关此类内容的参考,请参阅例如优秀而简短的 27 岁的 220 页 O'Reilly 书籍在 Unix 系统上使用 C,作者为 Dave Curry.
C language is used. I have a function that writes to stdout.
I would like to capture that output, modify it a bit (replacing some strings). And than output it again to the stdout. So I want to start with:
char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout); -OR- freopen("/dev/null", "a", stdout);
setbuf(stdout, huge_string_buffer);
/* modify huge_string_buffer */
The question is now, how do I output the huge_string_buffer back to the original stdout?
One idea is to mimic the functionality of the standard Unix utility tee
, but to do so entirely within your program, without relying on outside redirection.
So I've written a simple function, mytee()
, which seems to work. It uses shmget(), pipe(), fork(), and dup2()
:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
static char *mytee(int size) {
int shmid = shmget(IPC_PRIVATE, size + 1, 0660 | IPC_CREAT);
int pipe_fds[2];
pipe(pipe_fds);
switch (fork()) {
case -1: // = error
perror("fork");
exit(EXIT_FAILURE);
case 0: { // = child
char *out = shmat(shmid, 0, 0), c;
int i = 0;
out[0] = 0;
dup2(pipe_fds[0], 0); // redirect pipe to child's stdin
setvbuf(stdout, 0, _IONBF, 0);
while (read(0, &c, 1) == 1 && i < size) {
printf("<%c>", c); // pass parent's stdout to real stdout,
out[i++] = c; // and then buffer in mycapture buffer
out[i] = 0; // (the extra <> are just for clarity)
}
_exit(EXIT_SUCCESS);
}
default: // = parent
dup2(pipe_fds[1], 1); // replace stdout with output to child
setvbuf(stdout, 0, _IONBF, 0);
return shmat(shmid, 0, 0); // return the child's capture buffer
}
}
My test program is:
int main(void) {
char *mycapture = mytee(100); // capture first 100 bytes
printf("Hello World"); // sample test string
sleep(1);
fprintf(stderr, "\nCaptured: <%s>\n", mycapture);
return 0;
}
The output is:
To use this in your application, in mytee()
you'll need to replace the test statement printf("<%c>", c)
with just write(1, &c, 1)
. And you may need to handle signals in the call to read
. And after each of the two dup2()
's, you may want to add:
close(pipe_fds[0]);
close(pipe_fds[1]);
For a reference on this sort of stuff, see for example the excellent and short 27-year-old 220-page O'Reilly book Using C on the Unix System by Dave Curry.
这篇关于将标准输出捕获到字符串并将其输出回 C 中的标准输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!