在C中逐行读取管道

时间:2021-09-01 00:05:45

How can I separate the lines which are coming from a pipe. In the pipe there is this text:

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

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

I want to separate the lines from the pipe because i want to save the values in variables.

我想将管道与管道分开,因为我想将值保存在变量中。

Here is my c code:

这是我的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);
}

Is this the right way to read from pipe for the best line by line?

这是从管道读取最佳线路的正确方法吗?

2 个解决方案

#1


13  

This is usually just called reading from stdin. The program shouldn't care whether the input is a pipe, a redirected file, or a keyboard.

这通常只是从stdin读取。程序不应该关心输入是管道,重定向文件还是键盘。

fread will just read until the buffer is full. Use fgets to read a line.

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

Also the buffer size should be big enough to hold the line. For little one-off programs, you can just pick a number. Or there's a standard name BUFSIZ which gives you a pretty-big buffer. How big? Big enough. Really? Probably.

缓冲区大小也应足够大以容纳线路。对于小型一次性程序,您可以选择一个号码。或者有一个标准名称BUFSIZ,它为您提供了一个非常大的缓冲区。多大?足够大。真?大概。

fgets will copy the newline character in the string unless the string fills up first. So you can test the last character to tell if the line was truncated or not. With reasonable inputs, that's not going to happen. But a more robust approach would allocate a larger buffer, copy the partial line, and call fgets again tp keep trying to get a complete line.

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

This gets you halfway to being protected from the dreaded buffer overflow problem. fgets will not write more than the size passed to it. The other half, as mentioned above, is doing something sensible with the possible partial lines that may result from unexpectedly long input lines.

这可以帮助您免受可怕的缓冲区溢出问题的影响。 fgets的写入次数不会超过传递给它的大小。如上所述,另一半是对可能由于意外长输入线可能导致的部分线做了一些明智的事情。

#2


1  

Here's another option (I am not totally sure it is a 'proper' way)- use the number of bytes read by the read function. In this example I was reading from stdin although a redirection was made so the fd in 0 is a file/pipe/whatever you need it to be.

这是另一个选项(我不完全确定它是'正确'的方式) - 使用read函数读取的字节数。在这个例子中,我是从stdin读取的,虽然进行了重定向,因此0中的fd是文件/管道/无论你需要它。

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

#1


13  

This is usually just called reading from stdin. The program shouldn't care whether the input is a pipe, a redirected file, or a keyboard.

这通常只是从stdin读取。程序不应该关心输入是管道,重定向文件还是键盘。

fread will just read until the buffer is full. Use fgets to read a line.

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

Also the buffer size should be big enough to hold the line. For little one-off programs, you can just pick a number. Or there's a standard name BUFSIZ which gives you a pretty-big buffer. How big? Big enough. Really? Probably.

缓冲区大小也应足够大以容纳线路。对于小型一次性程序,您可以选择一个号码。或者有一个标准名称BUFSIZ,它为您提供了一个非常大的缓冲区。多大?足够大。真?大概。

fgets will copy the newline character in the string unless the string fills up first. So you can test the last character to tell if the line was truncated or not. With reasonable inputs, that's not going to happen. But a more robust approach would allocate a larger buffer, copy the partial line, and call fgets again tp keep trying to get a complete line.

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

This gets you halfway to being protected from the dreaded buffer overflow problem. fgets will not write more than the size passed to it. The other half, as mentioned above, is doing something sensible with the possible partial lines that may result from unexpectedly long input lines.

这可以帮助您免受可怕的缓冲区溢出问题的影响。 fgets的写入次数不会超过传递给它的大小。如上所述,另一半是对可能由于意外长输入线可能导致的部分线做了一些明智的事情。

#2


1  

Here's another option (I am not totally sure it is a 'proper' way)- use the number of bytes read by the read function. In this example I was reading from stdin although a redirection was made so the fd in 0 is a file/pipe/whatever you need it to be.

这是另一个选项(我不完全确定它是'正确'的方式) - 使用read函数读取的字节数。在这个例子中,我是从stdin读取的,虽然进行了重定向,因此0中的fd是文件/管道/无论你需要它。

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