ページ 1 / 1
fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 19:29
by only_note_on
#include <stdio.h>
#define SIZE_OF_EVENT 6
typedef struct event {
unsigned short int delta_time;
unsigned long int event_data;
} NTSEVENT;
int main(void) {
char filename[20];
NTSEVENT * evnt;
int i, j;
FILE * fin;
evnt = (NTSEVENT *)calloc(4,SIZE_OF_EVENT);
printf("読み込むファイル名を入力して下さい。:");
scanf("%s",filename);
if((fin = fopen(filename, "rb")) == NULL){
printf("Cannot open file %s\n", filename);
return 1;
}
i = 0;
while ( SIZE_OF_EVENT == fread(evnt + i, sizeof(char), SIZE_OF_EVENT, fin)){
i++;
}
for(j = 0; j < i; j++){
printf("%x\n",evnt[j].event_data);
}
fclose(fin);
free(evnt);
return 0;
}
読み込ませたバイナリファイルの中味は16進表記で
010012345678000412345678
となっています。
実行結果は
7856
7856
と出ます。
リトルエンディアンだとしても
78563412
78563412
となるはずだと思いますが、そうなりませんでした。
原因が分からないので、分かる方がいらっしゃいましたら教えてください。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 19:44
by bitter_fox
fread関数の使い方を間違っているようです。
fread関数の第二引数には、読み出す項目の一項目あたりのサイズを指定します。
第三引数は、読み出す項目の数を指定します。
ついでに、SIZE_OF_EVENTに定数を指定してますが、ここはsizeof(NTSEVENT)にしたほうがよいでしょう。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 19:53
by only_note_on
第二引数と第三引数を入れ替えて実行してみましたが同じ結果になりました。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:03
by softya(ソフト屋)
使っているコンパイル環境を教えて下さい。
環境次第では、アドレス境界の関係で構造体が6バイトではない可能性があります。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:07
by やんち
構造体のアライメントで引っ掛っている気がします。
一度、unsigned char 型の配列に読み込んで、自前でデコードした方が良いかも。
もしくは、コンパイルオプションで、アライメントの最適化を抑止するか。
「C言語 構造体 アライメント」で検索すると、何かヒントが見つかるかもしらん。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:21
by bitter_fox
データをこのように変えたらうまく表示されました。
01 00 00 00 12 34 56 78 00 04 00 00 12 34 56 78
やんちさんがおっしゃってるようにアライメントが働いて、読み込む際に、short int型も4バイト分読み込んでからshort int型の範囲にしているのが原因のようです。
PS:コードを載せる際はcodeタグで囲っていただきますようにお願いします。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:22
by a5ua
面倒でも、1メンバずつ読み込むのがいいと思います。
コード:
i = 0;
while (fread(&evnt[i].delta_time, sizeof(evnt[i].delta_time), 1, fin) == 1
&& fread(&evnt[i].event_data, sizeof(evnt[i].event_data), 1, fin) == 1
) {
i++;
}
追記:以下は勘違いでした。
それとは別に、SIZE_OF_EVENTの使用意図が、よくわかりません。
evnt = (NTSEVENT *)calloc(4,SIZE_OF_EVENT);
この行では、NTSEVENTのサイズとして使っているように見えますが、
while ( SIZE_OF_EVENT == fread(evnt + i, sizeof(char), SIZE_OF_EVENT, fin)){
ここでは、読み込む要素数として使っているように見えます。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:25
by only_note_on
コンパイラ環境はVC++2008EEとVC++6.0です。
C言語の構造体のアライメントについて調べまして、構造体の2つのメンバの順序を逆にして実行してみたところ、正しい値が入りました(リトルエンディアンではありますけども・・・)。
教えてくださってありがとうございました。(_ _)
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:37
by only_note_on
この掲示板を初めて利用して、フォーラムルールを読んでいませんでした。
次回からcodeタグは付けさせていただきます。
SIZE_OF_EVENTは読み込む領域のサイズを「何バイトがいくつ」のように書かなければいけないときには、sizeof(char)がSIZE_OF_EVENT分、というような書き方をしてバイト数を指定していました。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 21:59
by bitter_fox
only_note_on さんが書きました:
C言語の構造体のアライメントについて調べまして、構造体の2つのメンバの順序を逆にして実行してみたところ、正しい値が入りました(リトルエンディアンではありますけども・・・)。
解決とのことですが・・・
使用したデータはこれでしょうか??
[12 34 56 78 01 00 12 34 56 78 00 04]
これだと、僕の環境では(逆にしても)うまくいかなかったのですが・・・
(おそらく、逆にしてもアライメントされてるんじゃないかと思います。。。)
[hr]
[追記]
一項目あたりのバイト数を
としていたのですが、6を決め打つとうまく表示されました。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 22:09
by only_note_on
読み込むデータはまさしくそれと同じのを作って入れました。
読み込むファイルの方には構造体に入れて行きたいデータが6バイトずつ並んでいるという設定です。
sizeof(*evnt)とすると、構造体のアライメントで6ではなく8バイトが読まれてしまうのだと思います。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 22:17
by only_note_on
SIZE_OF_EVENTは人のソースコードの書き方を真似して書いたものですが、仕様意図はそこにあったのかもしれませんね。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 22:27
by softya(ソフト屋)
VC++の場合
#pragma pack(1)
でアライメントの変更ができます。
#pragma pack()
で戻すことも出来ます。
将来も使うならsizeof()で扱えるようにしておいたほうが良いと思いますよ。
Re: fread()関数がバイナリファイルを正しく読み込んでくれません
Posted: 2011年1月14日(金) 23:07
by only_note_on
アライメントを操作できれば、メモリの節約ができそうですね。
64bitパソコンともなるとなおさらかもしれません。
#pragma packは使わせていただきたいと思います。