在C语言中逐行读取管道内容

11

我如何将来自管道的行分开。在管道中有这个文本:

HALLO:500\n
TEST:300\N
ADAD
ADAWFFA
AFAGAGAEG

我想将管道符号中的行分隔开,这样我就可以把值保存在变量中。

这是我的C代码:

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

#define BUFFERSIZE    1

int main(int argc, char **argv){
    unsigned char     buffer[BUFFERSIZE];
    FILE                         *instream;
    int                            bytes_read=0;
    int                            buffer_size=0;


    buffer_size=sizeof(unsigned char)*BUFFERSIZE;
    /* open stdin for reading */
    instream=fopen("/dev/stdin","r");

    /* did it open? */
    if(instream!=NULL){
        /* read from stdin until it's end */
        while((bytes_read=fread(&buffer, buffer_size, 1, instream))==buffer_size){
            fprintf(stdout, "%c", buffer[0]);
        }
    }
    /* if any error occured, exit with an error message */
    else{
        fprintf(stderr, "ERROR opening stdin. aborting.\n");
        exit(1);
    }

    return(0);
}

这是从管道中逐行读取的正确方式吗?


“最好”的问题是主观的。您真的正在面临任何问题吗? - abasu
使用 fgets 替换 fread - Anish Ramaswamy
2个回答

20

这通常被称为从标准输入读取。程序不应关心输入是管道、重定向文件还是键盘。

fread将一直读取,直到缓冲区满。使用fgets读取一行。

另外,缓冲区大小应足够大以容纳整行内容。对于小型临时程序,您可以随便选一个数字。或者有一个标准名称BUFSIZ,它可以提供一个相当大的缓冲区。有多大?足够大了。真的吗?大概吧。

fgets将复制换行符到字符串中,除非字符串先被填满。所以您可以测试最后一个字符来判断行是否被截断。在合理的输入情况下,这种情况不太可能发生。但更健壮的方法是分配一个更大的缓冲区,复制部分行,并再次调用fgets尝试获取完整的行。

#include <stdio.h>

int main() {
    char buf[BUFSIZ];
    fgets(buf, sizeof buf, stdin);
    if (buf[strlen(buf)-1] == '\n') {
        // read full line
    } else {
        // line was truncated
    }
    return 0;
}

这能让你在避免可怕的缓冲区溢出问题上走了一半路。 fgets不会写入超过传递给它的大小。如上所述,另一半是针对可能导致意外长输入行的部分行执行一些明智的操作。


1
我愿意帮你,但你应该学会自己使用“man fgets”命令。(这是我写示例时首先要做的事情。如果不检查就写代码,我总是把参数搞反了。) - luser droog
1
我并不是想要听起来傲慢。我真的认为最好不要让我写这样的例子。 - luser droog
1
@bladepit,或者,一个在线手册应该会对你有所帮助 :) - Anish Ramaswamy
最后一个问题:使用fgets时,我需要指定要读取的行的长度吗? - bladepit
1
除了 BUFSIZ 之外,还有 LINE_MAX (<limits.h>)。在我的机器上,它比前者小一些(2048 vs 8192)。 - wastl
显示剩余2条评论

1
这里还有另一个选项(我不确定它是否是“正确”的方法)-使用read函数读取的字节数。 在这个例子中,我从stdin读取,尽管进行了重定向,因此0号文件描述符是文件/管道/任何您需要的内容。
  while ((nbytes=read(STDIN_FILENO, buffer, MAX_PIPE_SIZE)) > 0) {
    write(STDOUT_FILENO, buffer, nbytes);
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接