在 Linux 上使用 cat 命令通过 stdin 读取二进制数据

Posted

技术标签:

【中文标题】在 Linux 上使用 cat 命令通过 stdin 读取二进制数据【英文标题】:Reading binary data through stdin with cat command on linux 【发布时间】:2016-12-01 18:29:48 【问题描述】:

我正在尝试使用cat 命令通过stdin (0) 将二进制数据读取到我的程序中。我的程序的任务是将二进制更改为整数或双精度并将其写入所需的文件描述符。 当我运行命令:cat data_int.bin | ./myprogram -d 时,我无法读取任何内容,并且输入的大小为 0。但是当我尝试:./myprogram -d -I 0 0<data_int.bin 时,我的程序可以读取字节并成功完成。 我的代码:

#libraries

int main(int argc, char* argv[]) 

        int c;
        extern char *optarg;
        extern int optind;
        extern int optopt;

        char input_file[100] =  0 ;
        int nastavljen_input = 0;
        char output_file[100] =  0 ;
        int nastavljen_output = 0;
        int tip = -1; // 0 - char, 1- int, 2 - double
        int fd_in = 0;
        int fd_out = 1;
        while((c = getopt(argc,argv, ":o:i:O:I:cdf")) != -1) 
            switch(c) 
                case 'o':
                    strcpy(output_file,optarg);
                    nastavljen_output = 1;
                    fd_out = open(output_file,O_WRONLY);
                    break;
                case 'i':
                    strcpy(input_file,optarg);
                    nastavljen_input = 1;
                    fd_in = open(input_file,O_RDONLY);
                    break;
                case 'O':
                    fd_out = atoi(optarg);
                    break;
                case 'I':
                    fd_in = atoi(optarg);
                    break;
                case 'c':
                    tip = 0;
                    break;
                case 'd':
                    tip = 1;
                    break;
                case 'f':
                    tip = 2;
                    break;
            
        

        if(tip > -1) 
            struct stat st;
            fstat(fd_in, &st); //fd_in would be 0 with cat command
            int size = st.st_size; // number of bytes in input file
            printf("%d\n",size); // this will print out 0 with cat command

            unsigned char buffer[size];
            read(fd_in,buffer,size);

            ...code continues...

标志 -d 用于读取表示整数的字节, -I 用于选择输入文件描述符。在这种情况下,输出为 stdout(1)。 我的问题是,我的代码有问题还是这只是cat 命令的工作方式?我正在使用Xubuntu。 感谢您的时间和精力, 圆顶

【问题讨论】:

相关:UNIX/Linux IPC : Reading from a pipe. How to know length of data at runtime? 【参考方案1】:

管道总是有st_size 0,因为事先不知道将写入管道的字节流的长度。

许多程序在cat foo | progprog < foo 上的行为不同。这就是原因。在第二种情况下,prog 在标准输入上有一个常规文件,因此stat 显示大小。同样在第二种情况下,lseek/fseek 将起作用,而在管道上则不起作用。

如果您想将标准输入的内容读入缓冲区,并且当标准输入是管道时您需要它来工作,您必须猜测它的大小,然后跟踪您读取了多少以及何时读取内存不足,再分配一些。 realloc 很适合这个。

【讨论】:

我将缓冲区大小更改为 20 并将 nbytes 读取为 20。仍然,我什么也没得到... 20 是二进制文件的完整大小。 ssize_t read(int fildes, void *buf, size_t nbyte) - 我将 nbyte 设置为 20,将缓冲区大小设置为 buffer[20]。 @domenkavran 当我这样做时,read 如您所愿返回 20。 @thatotherguy 我的错。这行得通。但我的下一个问题是如何在执行时确定或更改缓冲区的大小?重新分配可能太大。 为什么在转换之前需要将整个文件读入内存?你不能一次转换 8 个字节吗?

以上是关于在 Linux 上使用 cat 命令通过 stdin 读取二进制数据的主要内容,如果未能解决你的问题,请参考以下文章

Linux more(功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上)

Linux上常用命令整理—— cat

linux学习笔记9--命令cat

每天一个Linux命令cat(2)

每天一个Linux命令cat -b(2)

每天一个Linux命令cat -b(2)