在C中使用popen()不成功?

在C中使用popen()不成功?,c,screenshot,popen,piping,x11,C,Screenshot,Popen,Piping,X11,我可以运行以下命令 xwd-root | xwdtopnm | pnmtojpeg>screen.jpg 在linux下的终端中,它将生成我当前屏幕的屏幕截图 我尝试对代码执行以下操作: #include <stdio.h> #include <stdlib.h> int main() { FILE *fpipe; char *command="xwd -root | xwdtopnm | pnmtojpeg"; char line[256];

我可以运行以下命令

xwd-root | xwdtopnm | pnmtojpeg>screen.jpg

在linux下的终端中,它将生成我当前屏幕的屏幕截图

我尝试对代码执行以下操作:

#include <stdio.h>
#include <stdlib.h>
int main()
{
   FILE *fpipe;
   char *command="xwd -root | xwdtopnm | pnmtojpeg";
   char line[256];

   if ( !(fpipe = (FILE*)popen(command,"r")) )
   {  // If fpipe is NULL
      perror("Problems with pipe");
      exit(1);
   }

   while ( fgets( line, sizeof line, fpipe))
   {
      //printf("%s", line);
      puts(line);
   }
   pclose(fpipe);
}
#包括
#包括
int main()
{
文件*fpipe;
char*command=“xwd-root | xwdtopnm | pnmtojpeg”;
字符行[256];
if(!(fpipe=(FILE*)popen(命令,“r”))
{//如果fpipe为NULL
perror(“管道问题”);
出口(1);
}
而(fgets(管线、管线尺寸、管道))
{
//printf(“%s”,第行);
放(线);
}
pclose(fpipe);
}

然后我编译并运行程序
/popen>screen.jpg
,但生成的文件screen.jpg是不可重组的。如何才能正确地通过管道传输程序?

在不测试代码的情况下,我怀疑“xwd-root | xwdtopnm | pnmtojpeg”是否可以用作C-pipe的参数


对于这样的问题,我无论如何都不会使用C程序。使用简单的Bash脚本。

处理二进制数据时不应使用
fgets
put
fgets
将在看到换行符时停止。更糟糕的是,
put
将输出额外的换行符,并且每当它运行到\0时,它也将停止。改用
fread
fwrite

函数
fgets
put
不用于图像文件等二进制数据。它们只能与文本字符串一起使用。在C语言中,字符串以空字节结尾(
'\0'
)。因为这实际上只是一个零,所以它可能出现在二进制文件中的任何位置。假设
行[]
中填充了256个字符的数据。调用
put
时,函数读取数组,直到遇到空字节,然后假设它已到达字符串末尾并停止。由于在二进制文件中,空字节可能出现在任何地方(而不仅仅是在数组末尾),因此
put
函数很容易无法打印出数据的各个部分


如果我是你,我会研究
fread
fwrite
函数并使用它们。在Linux机器上,您只需键入
man 3 fread
即可阅读这两个函数的文档。

对于存在相同问题的用户,我最终通过使用Unix读/写系统调用使其正常工作:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

//writes to an output file test.jpg directly
int main()
{
    FILE *fpipe;
    char *command="xset b off  && xwd -root | xwdtopnm 2> /dev/null | pnmtojpeg";
    char buff[256];
    size_t result_write;
    size_t result_read;

    if ( !(fpipe = (FILE*)popen(command,"r")) )
    {  // If fpipe is NULL
        perror("Problems with pipe");
        exit(1);
    }

    int dest_fd = open("test.jpg",  O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR );
    int fd = fileno(fpipe);
    while((result_read = read(fd, buff, sizeof(char)*256))>0){  
        if(result_read < 0){
            perror("Problem while reading.\n");
            exit(1);
        }
        result_write = write(dest_fd, buff, sizeof(char)*256);
        if(result_write < 0){
            perror("Probelms writing to outputfile.\n");
            exit(1);
        }   
    }
    close(dest_fd);     
   pclose(fpipe);
}
#包括
#包括
#包括
#包括
#包括
//直接写入输出文件test.jpg
int main()
{
文件*fpipe;
char*command=“xset b off&&xwd-root | xwdtopnm 2>/dev/null | pnmtojpeg”;
字符buff[256];
大小\u t结果\u写入;
读取结果的大小;
if(!(fpipe=(FILE*)popen(命令,“r”))
{//如果fpipe为NULL
perror(“管道问题”);
出口(1);
}
int dest_fd=open(“test.jpg”,O|RDWR | O|TRUNC | O|u CREAT,S|IRUSR | S|IWUSR);
int fd=文件编号(fpipe);
而((result_read=read(fd,buff,sizeof(char)*256))>0{
如果(结果读数<0){
perror(“读取时出现问题。\n”);
出口(1);
}
结果写入=写入(dest\u fd,buff,sizeof(char)*256);
如果(结果写入<0){
perror(“写入输出文件的问题。\n”);
出口(1);
}   
}
关闭(目的地fd);
pclose(fpipe);
}

我不能使用Bash脚本,这只是一个测试。我需要一种编程的方式在X11中截图,这是我在不阅读所有X11源代码的情况下能想到的最好的方法。对不起,我指的是fread和fwrite,而不是读写。(刚刚编辑了我的答案)只要确保不在同一个文件上执行缓冲IO(fread、fscanf、fwrite、fprintf…)和非缓冲IO(读取、写入…),就可以了。但我不明白你为什么不使用fread和fwrite。