0

ソケット経由でテキスト ファイルを送信するために、テキスト ファイルをバッファにコピーしようとしています。テキスト ファイルに改行 (または \n) がなくなるとすぐに、ファイルは正常にバッファーにコピーされます。しかし、テキスト ファイルに複数の行があると、「ファイルをバッファにコピーできません」というエラーが表示されます。

以下はコード スニペットです。

//=====================Sending a File at Socket=========================
   FILE *fp = fopen("File.txt", "r+");
   char file_buffer[1000];

   fseek(fp, 0, SEEK_END);
   size_t file_size = ftell(fp); //calculating File Size

   fseek(fp, 0, SEEK_SET);
   int bytes_read=0;
   if((bytes_read=fread(file_buffer, 1, file_size, fp))<=0)
     {
       MessageBox( NULL,
               "Unable to copy file into buffer",
               "Error!",
               MB_ICONEXCLAMATION | 
               MB_OK);
      exit(1);
     }
     MessageBox( NULL,
             file_buffer,
            "File copied in Buffer",
            MB_ICONEXCLAMATION | 
            MB_OK);

注: テキスト ファイルに新しい行が含まれていない場合、コードは問題なく動作します。

4

1 に答える 1

3

簡潔な答え

「r+」モードではなく「rb+」モードでファイルを開き、


長い答え

「r+」モードでファイルを開いています。このモードでは、すべての "\r\n" シーケンス (つまり、Windows の行末) が "\n" (つまり、Unix の行末) に変換されます。

ただし、 ftell によって返されるファイル サイズは、変換なしで実際のファイル サイズを示します。

File.txt の内容

12\r\n34

このファイルのサイズは 6 バイトです

「r+」モードでの fread 後の file_buffer の内容:

12\n34

その場合、fread の戻り値は 5 になります。

「rb+」モードでの fread 後の file_buffer の内容:

12\r\n34

その場合、fread の戻り値は 6 になります。これはデバッガーで確認できます。fopenのドキュメントを読んでください。

コード内のその他の問題

MessageBox を呼び出すと、ゼロ ターミネータを配置していないため、ファイルの内容の後にゴミが表示される可能性があります。

freadの呼び出しの後にこれをプログラムに追加します

file_buffer[bytes_read] = 0 ;

戻り値が < 0 であるかどうかをテストすることによって fread でエラー状態をテストすることは正しくありません。とにかく、fread の戻り値の型は size_t (符号なし) であり、int ではsize_t bytes_read=0;なく、代わりに書き込みますint bytes_read=0;

freadのドキュメントからの抜粋:

fread は、実際に読み取られた完全なアイテムの数を返します。エラーが発生した場合、または count に達する前にファイルの終わりに達した場合、これは count 未満になることがあります。読み取りエラーとファイルの終わりの状態を区別するには、feof または ferror 関数を使用します。size または count が 0 の場合、fread は 0 を返し、バッファーの内容は変更されません。stream または buffer が null ポインターの場合、「パラメーターの検証」で説明されているように、fread は無効なパラメーター ハンドラーを呼び出します。実行の継続が許可されている場合、この関数は errno を EINVAL に設定し、0 を返します。

于 2013-05-08T07:05:51.193 に答える