【问题标题】:Read from pipe line by line in C在 C 中逐行读取管道
【发布时间】:2013-04-16 07:14:53
【问题描述】:

如何分隔来自管道的线路。在管道中有这样的文字:

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);
}

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

【问题讨论】:

  • for the best 是一个主观问题。你真的遇到什么问题了吗?
  • fread 替换为fgets

标签: c pipe stdout stdin


【解决方案1】:

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

fread 只会读取直到缓冲区已满。使用 fgets 读取一行。

缓冲区大小也应该足够大以容纳行。对于小的一次性程序,您可以选择一个数字。或者有一个标准名称BUFSIZ,它为您提供了一个相当大 的缓冲区。多大?足够大。真的吗?大概吧。

fgets 将复制字符串中的换行符,除非字符串先填满。因此,您可以测试最后一个字符以判断该行是否被截断。有了合理的投入,这不会发生。但更强大的方法是分配更大的缓冲区,复制部分行,然后再次调用fgets tp 继续尝试获得完整的行。

#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 不会写入超过传递给它的大小。如上所述,另一半正在对可能由意外长输入行导致的部分行做一些明智的事情。

【讨论】:

  • 我愿意。但是你应该学会为自己做man fgets。 (这是我写一个例子的第一件事。当我写而不检查时,我总是把论据倒过来。)
  • 我不想让自己听起来很流氓。我真的认为最好不要写这样的例子。
  • @bladepit,或者,online manual 应该可以帮助你:)
  • 是的,没错。我看看手册,希望直到今天下午我才能解决我的问题
  • 除了BUFSIZ,还有LINE_MAX&lt;limits.h&gt;)。在我的机器上它更少(2048 vs 8192)。
【解决方案2】:

这是另一种选择(我不完全确定这是一种“正确”的方式)-使用read 函数读取的字节数。 在此示例中,我从 stdin 读取,尽管进行了重定向,因此 0 中的 fd 是文件/管道/您需要的任何内容。

  while ((nbytes=read(STDIN_FILENO, buffer, MAX_PIPE_SIZE)) > 0) {
    write(STDOUT_FILENO, buffer, nbytes);
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 2010-11-19
    • 1970-01-01
    相关资源
    最近更新 更多