0

私は C でいくつかのファイル操作手法を試していたので、ファイルを入力として受け取り、それを空のファイルにコピーする簡単なプログラムを作成しました。「バイナリ」および「読み取り」モードで fopen() を使用して読み取り対象のファイルを開き、fgetc() を使用してすべてのバイトを 1 つずつ読み取り、「書き込み」および「書き込み」モードで開かれた、書き込みたいファイルにそれらを書き込みました。バイナリモード。コピー操作が終了すると (EOF)、両方のファイルで fclose() を呼び出してプログラムを終了しました。

ここに問題があります。テキスト ファイルの場合はすべて問題なく動作しますが、pdf や jpeg などの別の形式でファイルをコピーしようとすると、セグメンテーション エラーが発生します。コードは非常に短く単純なので、この問題はコードのバグではなく、C でこれらのファイル形式を読み書きする方法を理解していないことが原因であると思われます。

提案やアイデアは大歓迎です。コードに何か問題があると思われる場合は、投稿することもできます。

編集:わかりましたので、おそらくコードを台無しにしました。ここにあります:

#include <stdio.h>
#include <stdlib.h>

#define MAXCHAR 10000000

int main( int argc, char** argv)
{
    if( argc != 3)
    {
        printf( "usage: fileexer1 <read_pathname> <write_pathname>");
        exit( 1);
    }

    FILE* file_read;
    FILE* file_write;

    int nextChar;
    char readBuffer[MAXCHAR];
    int valid = 0;

    // These hold the path addresses to the files to be read and written
    char* read_file_path = argv[1];
    char* write_file_path = argv[2];

    // The file to be read is opened in 'read' and 'binary' modes
    file_read = fopen( read_file_path, "rb");
    if( !file_read)
    {
        perror( "File cannot be opened for reading");
        exit( 1);
    }

    // The file to be written into is opened in 'write' and 'binary' modes
    file_write = fopen( write_file_path, "wb");
    if( !file_write)
    {
        perror( "File cannot be opened for writing");
        exit( 1);
    }

    nextChar = fgetc( file_read);
    while( nextChar != EOF)
    {
        readBuffer[valid] = (char) nextChar;
        valid++;
        nextChar = fgetc( file_read);
    }

    int i;
    for( i = 0; i < valid; i++)
    {
        fputc( readBuffer[i], file_write);
    }

    fclose( file_read);
    fclose( file_write);

   return 0;
}
4

3 に答える 3

0

とにかく文字単位で読み書きする場合、データを保持するために巨大なバッファを割り当ててもほとんど意味がありません。エラーチェックを無視:

int main(int argc, char **argv) { 

   FILE *infile = fopen(argv[1], "rb");
   FILE *outfile = fopen(argv[2], "wb");

   int ch;

   while (EOF != (ch = getc(infile)))
      putc(ch, outfile);

   return 0;
}
于 2012-09-06T18:31:03.913 に答える
0

一度に 1 文字ずつ読み取る場合、スタック上のバ​​ッファーに 1000 万文字を保存する必要はありません。また、コードは 1,000 万バイトを超えるファイルを適切に処理できません。

fputc(nextChar)呼び出しの前に入力ループで使用し、変数と出力ループfgetc()を削除します。readBuffer必要に応じて有効な文字を数えることもできますが、その必要はありません。

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char** argv)
{
    if( argc != 3)
    {
        printf( "usage: fileexer1 <read_pathname> <write_pathname>");
        exit( 1);
    }

    FILE* file_read;
    FILE* file_write;

    int nextChar;

    // These hold the path addresses to the files to be read and written
    char* read_file_path = argv[1];
    char* write_file_path = argv[2];

    // The file to be read is opened in 'read' and 'binary' modes
    file_read = fopen( read_file_path, "rb");
    if( !file_read)
    {
        perror( "File cannot be opened for reading");
        exit( 1);
    }

    // The file to be written into is opened in 'write' and 'binary' modes
    file_write = fopen( write_file_path, "wb");
    if( !file_write)
    {
        perror( "File cannot be opened for writing");
        exit( 1);
    }

    while ((nextChar = fgetc(file_read)) != EOF)
        fputc(nextChar, file_write);

    fclose( file_read);
    fclose( file_write);

   return 0;
}

一部のシステムでは、10 MiB スタックに問題があることに注意してください。より効率的にしたい場合は、64 KiB バッファーの使用を検討してから、 と を使用fread()fwrite()てデータのチャンクを読み書きします。

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char** argv)
{
    if( argc != 3)
    {
        printf( "usage: fileexer1 <read_pathname> <write_pathname>");
        exit( 1);
    }

    FILE *file_read;
    FILE *file_write;
    char buffer[64*1024];
    size_t nbytes;

    // The file to be read is opened in 'read' and 'binary' modes
    file_read = fopen(argv[1], "rb");
    if (!file_read)
    {
        perror("File cannot be opened for reading");
        exit(1);
    }

    // The file to be written into is opened in 'write' and 'binary' modes
    file_write = fopen(argv[2], "wb");
    if (!file_write)
    {
        perror("File cannot be opened for writing");
        exit(1);
    }

    while ((nbytes = fread(buffer, sizeof(buffer), sizeof(char), file_read)) != EOF)
    {
        if (fwrite(buffer, nbytes, sizeof(char), file_write) != nbytes)
        {
            perror("Failed to write to file");
            exit(1);
        }
    }

    fclose(file_read);
    fclose(file_write);

   return 0;
}

を使用perror()すると、メッセージの有用性が制限されます。を使用するfprintf(stderr, ...)ことをお勧めしますが、私はそれを修正していません。

于 2012-09-06T18:31:06.770 に答える