• ベストアンサー

ファイル読み込みエラーになる。

ファイル読み込み時に読み込んだデータサイズと、それを格納するストラクタのsizeofで取得したサイズが異なる為エラーになってしまいます。 実際のデータ→10バイト 構造体→WORD、DWORD、DWORDの10バイト なのですが、 blRet = ReadFile(hNDFile[bFile], cpReadData, sizeof(構造体),&outFileSize, 0 ); とすると、構造体のsizeofの値が12になる為関数は戻り値1(エラー)で返ってきてしまいます。 取得した値自体は問題ないのですが。。 逆にこの問題を解決しようとして構造体宣言の部分を#pragma pack(push , 1)で囲うと、sizeof(構造体)の値は10バイトとなり、readfile関数は正常に終わるのですが、読み取ったデータの値が想定していないものになってしまいます。 何がおかしいかわからず困っています。。

質問者が選んだベストアンサー

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

それは当たり前です。 構造体が、WORD、DWORD、DWORDだとしたら実際のメモリ上では、WORD、2バイトの余白、DWORD、DWORDと配置されています。 10バイトしか読み込みしないと最後のDWORDの途中までしか読み込んでいません。リトルエンディアンだと起きる大きな勘違いで、最後のDWORDの値が65536を超えているとちゃんと読めないはずです。 #pragma pack(push , 1) でちゃんと読めないのは、もともと出力されているはファイルが #pragma pack(push , 1) で出力されていないからではないですか? 解決法は、 DWORD、DWORD、WORD で入出力を統一することです。

lasichi
質問者

補足

回答ありがとうございます。 実際のデータはサイズはバイナリで10バイトなのです。 ※データのアライメントは1バイト並びだそうです。 ですのでDWARDで統一すると12バイトになりますよね? そうするとReadFile関数で該当ファイルを読み込んだ場合、実際の読み込んだファイルサイズが10バイト、sizeof(構造体)のサイズが12バイトとなり、エラーになってしまうのです。。 エラーといってもReadFileの戻り値に1が帰ってくるだけで、読み込んだ値は正しく取得出来ているようです。 構造体のサイズをsizeof(構造体)ではなく、10と直に入力すると一番希望通りの処理になるのですが、他のファイル読み込みでも使用する関数の為無理です。。 初心者ですので変な事を言っていたらすいません。。

その他の回答 (6)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.7

★追記。 ・データのアライメントは1バイトでもプログラムが1バイトではないので  データとプログラムの両方のアライメントを合わせる必要があります。 ・データのアライメントは1バイトなのでプログラムを作り直せば良いです。  コンパイルのオプション設定を回答 No.6 を参考に変更してコンパイルを  やり直せばよい。これで ReadFile() の戻り値と sizeof(構造体)のバイト数が  一致します。 ・以上。

lasichi
質問者

お礼

沢山の回答ありがとうございました。 結局もらったデータが仕様書と間違っていた事が判明しました。 そりゃあ矛盾が生じるわけですね。。 為になるアドバイス助かりました。 ですがいろいろ勉強する良い機会になりました。 ありがとうございました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.6

★もう一つの方法 ・コンパイル・オプションを変更する方法もある。  構造体の場合は1、2、4、8、16バイトにアライメントされます。  処理系により初期値が違いますが BCC では1バイトに VC 系では4バイトに  なっていたりします。デフォルトですのでオプションで変更できます。 ・処理系(コンパイラ)が分かりませんが VC ならプロジェクトのプロパティから  『C/C++』→『コード生成』→『構造体のアライメント』の設定を変更します。  変更する時『既定値』から『1バイト /Zp1』にします。  他の処理系でもオプションで変更できます。 ・構造体のアライメントを1バイトに変更すると正しくなります。  ただし一度作成したデータファイルはもう一度作り直す必要があります。 ・以上。

回答No.5

そうですね。 対策は2つあります。 (1)プログラムは、#pragma pack(push,1)なしにする。 ファイルを作るプログラムは、出力サイズを単純に10としないで、sizeof(構造体)を使う。 (2)#pragma pack(push,1)を使うなら、ファイル作成とファイル入力の両方で使わないとだめです。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.4

回答者#1&#3です。 やはり私の思った通りのデータでした。 19 22 00 00 01 00 00 00 0A 00 をデータに分解すると [19 22] WORD 0x2219で10進で8729。 [00 00] WORD。たぶん2バイトの余白。 [01 00 00 00] DWORD 0x00000001で10進で1。 [0A 00] WORD 0x000Aで10進で10。 となり最後がDWORDで4バイトのはずがWORDで2バイトしかありません。 ですので、#1の回答の通りにすべきです。 今の段階では、読み込みべきデータファイルが破損している状態ですね。 ちなみに#pragma pack(push , 1)で読み込むと、 [19 22] WORD 0x2219で10進で8729。 [00 00 01 00] DWORD 0x00010000で10進で65536。 [00 00 0A 00] DWORD 0x000A0000で10進で655360。 となるはずですが? もしならないなら、別に他の問題があるのかも。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

私もデータが見たいですね。 ファイルの内容を16進ダンプしたものが見たいです。 バイナリエディタなどで表示して、コピペしてください。 もちろん、WORD、DWORD、DWORに入っているはずの値もほしいです。

回答No.2

実際のデータのWORD、DWORD、DWORDの値と、プログラムで読み込んだデータをprintfしたものを教えてください。

lasichi
質問者

補足

バイナリエディタで開いたところ 19 22 00 00 01 00 00 00 0A 00 です。 WORD→正確な値は不明 DWORD→1 DWORD→10 になっていれば正しい値です。 プログラムで読み込んだ場合、pragmaを付けると 1→256 10→65535?になってしまいます。 pragmaを付けないと値は正常に取得出来るのですが、Readfile関数でエラーが返ってきてしまいます。。

関連するQ&A