问题
I can run the following command
xwd -root | xwdtopnm | pnmtojpeg > screen.jpg
in a terminal under linux and it will produce a screenshot of my current screen.
I try to do the following with the code:
#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);
}
then I compile and run the program ./popen > screen.jpg
but the resulting file screen.jpg is unrecongizable. How can I do this so that I can pipe through my program correctly?
回答1:
You shouldn't use fgets
and puts
for dealing with binary data. fgets
will stop whenever it sees a newline. Worse, puts
will output extra newlines and it will also stop whenever it runs into a \0. Use fread
and fwrite
instead.
回答2:
The functions fgets
and puts
aren't intended to be used with binary data like image files. They should only be used with strings of text. In C, strings end with a null byte ('\0'
). Since that's really just a zero, it might appear anywhere in a binary file. Let's say that line[]
is filled with 256 characters of data. When you call puts
, the function reads the array until it encounters a null byte then assumes it has reached the end of the string and stops. Since in a binary file a null byte might appear anywhere (and not just at the end of the array), the puts
function could easily fail to print out sections of your data.
If I were you, I'd research the fread
and fwrite
functions and use them instead. On a Linux machine, you should just be able to type man 3 fread
to read documentation for both functions.
回答3:
For those having this same problem, I ended up finally getting it working by using the Unix read/write system calls:
#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);
}
回答4:
Without testing your code I hav doubts that "xwd -root | xwdtopnm | pnmtojpeg" works as an argument for a C - Pipe.
I wouldn't use a C program anyway for such a problem. Use a simple Bash script instead.
来源:https://stackoverflow.com/questions/839232/unsuccessful-use-of-popen-in-c