4

次のコマンドを実行できます

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

次に、プログラムをコンパイルして実行します./popen > screen.jpgが、結果のファイル screen.jpg は認識できません。プログラムを正しくパイプ処理できるようにするにはどうすればよいですか?

4

4 に答える 4

7

バイナリ データの処理にfgetsandを使用しないでください。改行が表示されるたびに停止します。さらに悪いことに、余分な改行が出力され、\0 に遭遇するたびに停止します。代わりにandを使用してください。putsfgetsputsfreadfwrite

于 2009-05-08T10:46:25.787 に答える
2

これと同じ問題を抱えている人のために、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);
}
于 2009-05-08T20:34:27.270 に答える
2

関数fgetsputsは、画像ファイルなどのバイナリ データで使用することを意図していません。これらは、テキストの文字列でのみ使用する必要があります。C では、文字列は null バイト ( '\0') で終わります。これは実際には単なるゼロであるため、バイナリ ファイルのどこにでも表示される可能性があります。line[]256 文字のデータで満たされているとしましょう。を呼び出すputsと、関数は null バイトに到達するまで配列を読み取り、文字列の末尾に到達したと見なして停止します。バイナリ ファイルでは null バイトが (配列の末尾だけでなく) どこにでも現れる可能性があるため、puts関数は簡単にデータのセクションの出力に失敗する可能性があります。

私があなただったら、関数と関数を調べfreadfwrite代わりに使用します。man 3 freadLinux マシンでは、入力するだけで両方の機能のドキュメントを読むことができるはずです。

于 2009-05-08T11:02:30.960 に答える
0

コードをテストしないと、「xwd -root | xwdtopnm | pnmtojpeg」が C パイプの引数として機能することに疑問があります。

とにかく、そのような問題にはCプログラムを使用しません。代わりに単純な Bash スクリプトを使用してください。

于 2009-05-08T10:42:52.787 に答える