web-dev-qa-db-ja.com

バイナリファイルを1バイトずつ読み取る

私は一度にC 1バイトのバイナリファイルを読み取ろうとしていますが、インターネットで何時間も検索した後でも、ガベージやセグメンテーションフォールト以外は取得できません。基本的に、バイナリファイルは256項目長のリスト形式で、各項目は1バイト(0〜255の符号なし整数)です。 fseekとfreadを使用して、バイナリファイル内の「インデックス」にジャンプし、その値を取得しようとしています。私が現在持っているコード:

unsigned int buffer;

int index = 3; // any index value

size_t indexOffset = 256 * index;
fseek(file, indexOffset, SEEK_SET);
fread(&buffer, 256, 1, file);

printf("%d\n", buffer);

現在、このコードはランダムなガベージ番号とセグメンテーションフォールトを提供しています。これを正しく機能させるためのヒントはありますか?

18
RogerB

コードでは、256バイトを1つのintのアドレスに読み取ろうとしています。一度に1バイトを読み取りたい場合は、fread(&buffer, 1, 1, file);を呼び出します( fread を参照)。

しかし、より簡単な解決策は、バイトの配列を宣言し、すべてをまとめて読み取り、その後処理することです。

16
MByD

紛らわしいbytes with intbyteの一般的な用語はnsigned charです。ほとんどのバイトは8ビット幅です。読み取り中のデータが8ビットの場合、8ビットで読み取る必要があります。

#define BUFFER_SIZE 256

unsigned char buffer[BUFFER_SIZE];

/* Read in 256 8-bit numbers into the buffer */
size_t bytes_read = 0;
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr);
// Note: sizeof(unsigned char) is for emphasis

すべてのデータをメモリに読み込む理由は、I/Oのフローを維持するためです。要求された数量に関係なく、各入力要求に関連付けられたオーバーヘッドがあります。一度に1バイトを読み取るか、一度に1つの位置をシークするのが最悪のケースです。

1バイトの読み取りに必要なオーバーヘッドの例を次に示します。

Tell OS to read from the file.
OS searches to find the file location.
OS tells disk drive to power up.
OS waits for disk drive to get up to speed.
OS tells disk drive to position to the correct track and sector.
-->OS tells disk to read one byte and put into drive buffer.
OS fetches data from drive buffer.
Disk spins down to a stop.
OS returns 1 byte to your program.

プログラム設計では、上記のステップが256回繰り返されます。みんなの提案で、「->」でマークされた行は256バイトを読み取ります。したがって、同じ量のデータを取得するために、オーバーヘッドは256回ではなく1回だけ実行されます。

15
Thomas Matthews
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);

私が信じる男を読む時です。

3
c-smile

256バイトを「バッファ」と呼ばれる4バイト整数変数に読み取ろうとしています。次の252バイトの他のデータを上書きしています。

bufferは_unsigned char buffer[256];_であるか、fread(&buffer, 1, 1, f)である必要があり、その場合はbufferは_unsigned char buffer;_である必要があります。

あるいは、1文字だけが必要な場合は、bufferintのままにしておくことができます(nsignedは必要ありません。C99はプレーンintの妥当な最小範囲を保証するためです)そして、単に言う:

_buffer = fgetc(f);
_
0
DigitalRoss

現状のコードに関するいくつかの問題。

Freadのプロトタイプは次のとおりです。

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

サイズを256(バイト)に設定し、カウントを1に設定しました。これで問題ありません。つまり、「256バイトの塊を1つ読んで、バッファーに押し込む」ということです。

ただし、バッファーの長さは2〜8バイト(または、少なくとも256バイトよりも大幅に小さい)なので、バッファーオーバーランが発生します。おそらくfred(&buffer、1、1、file)を使用したいでしょう。

さらに、バイトデータをintポインターに書き込んでいます。これは1つのエンディアン(実際にはスモールエンディアン)で機能するため、Intelアーキテクチャは問題なく使用できます。

バイトデータをintやfloatではなく、バイト構成のストレージにのみ書き込むようにしてください。

0
Vatine