• ベストアンサー

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

ファイル読み込み時に読み込んだデータサイズと、それを格納するストラクタの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

  • ReadFileの読み込みエラーについて

     こんばんは Win32 APIでプログラミングをやっているのですが、そのAPIの中でReadFileというものがありますよね? この関数でエラー値が出力され、第二引数としてBITMAPINFO構造体に格納するはずの値がそのままです。 以下に一部ソースを載せます BOOL Cell_Init( HINSTANCE hInstance ) { BITMAPINFO bmi2; HANDLE hFile; DWORD dwBytes; // 作成するビットマップの情報を設定する BITMAPFILEHEADER bmpFileHeader; BITMAPINFO bmi; // ビットマップのハンドルと、作成したバッファの先頭アドレスを取得 void* pImage; HBITMAP hBitmap; // デスクトップのDCを得る HDC tmpDC = GetDC(GetDesktopWindow() ); // HBITMAPにHDCを結びつける g_hdc_cell = CreateCompatibleDC( tmpDC ); DWORD er; hFile = CreateFile("cointos.bmp", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); er = GetLastError(); if(hFile == INVALID_HANDLE_VALUE) return 0; ReadFile(hFile, &bmpFileHeader, sizeof(BITMAPFILEHEADER), &dwBytes, NULL); er = GetLastError(); if(bmpFileHeader.bfType != 0x4D42) { MessageBox(NULL, TEXT("This is not a bitmap file"), NULL, MB_OK); return FALSE; }       //ここでbmi2に格納される値が格納されていない(そのためでかい値のまま) そのためCreateDIBSectionではエラーを起こす ReadFile(hFile, &bmi2, bmpFileHeader.bfOffBits - dwBytes, &dwBytes, NULL); er = GetLastError(); // ここの部分でエラー値998が出ます hBitmap = CreateDIBSection(tmpDC, &bmi2, DIB_RGB_COLORS, (LPVOID*)&pImage, NULL, 0); ReadFile(hFile,pImage, bmpFileHeader.bfSize - bmpFileHeader.bfOffBits, &dwBytes, NULL); SelectObject( g_hdc_cell, hBitmap ); CloseHandle(hFile); ReleaseDC(GetDesktopWindow(), tmpDC); return TRUE; } なぜこうなるんでしょうか? bmi2はBITMAPINFO構造体でローカルで宣言しています。これがポインタだと大丈夫なんですが なぜ変数ではダメなのか分かりません。 あらかじめ確保されているスタック領域の容量限界でも ないと思うのですが。 分かる方がいらっしゃったらよろしくお願いします。 開発環境はVS.2005 です。

  • #pragmaについて

    下記の構造体1、構造体2、使うとき何か違いますか。 ソースAのL4のところ、構造体2の場合は問題がないですが、構造体1だったらエラーになりました。落ちろ原因を教えて頂けませんか。 ソースA: L1: ST_POSTING_CHUNK* pChunk = m_pDocFreqList->m_pHeadChunk; L2: while(pChunk) L3: { L4: pDocFreqOutput->write((const char*)pChunk->data,pChunk->size); L5: pChunk = pChunk->next; L6: } 構造体S1: #pragma pack(push,1) struct ST_POSTING_CHUNK { long size; ST_POSTING_CHUNK* next; unsigned char data[1]; }; #pragma pack(pop) 構造体2: #pragma pack(push,1) struct ST_POSTING_CHUNK { long   size; unsigned char   data[1];     ST_POSTING_CHUNK* next; }; #pragma pack(pop)

  • 非同期のプロセス間通信(パイプ)で全データ受信する

    こんにちは。 非同期のプロセス間通信(パイプ)で詰まっています。 環境はWindowsで処理系はC++(Win32)です。 スレッドを用意して、 hPipe = ::CreateFile( L"\\\\.\\pipe\\pipename", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ) ; で作成し、OVERLAPPED構造体を // ZeroMemory( &so, sizeof( OVERLAPPED )) ; sOverlapped.hEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; として、 const size_t bufsize = 16 ; BYTE     buffer[ uBufSize ] ; DWORD    dwNumberOfBytesRead ; bRet = ::ReadFile( hPipe, buffer, bufsize, &dwNumberOfBytesRead, &so ) ; で読み込みをしています。ReadFile関数はすぐ戻りbRetはFALSEで返ってくるため、GetLastErrorを調べて、 switch( ::GetLastError()) {   case ERROR_IO_PENDING :     bRet = ::GetOverlappedResult( hPipe, &so, &dwNumberOfBytesRead, FALSE ) ;     break ; } としてWaitForMultipleObjectsでsOverlapped.hEventがシグナル状態になったら取得したデータの処理をしています。 シグナル状態になるならないに関わらず、上記のReadFileとGetOverlappedResultはループでぐるぐる回しています。 上記の状態で短いデータならよかったのですが、上記のReadFileで読み込み最大サイズの16バイトを超えてしまとうと、 残りの部分のみしか取得できませんでした。 0123456789ABCDEFabcdefg というデータを受信しようとしたとき、後半のabcdefgだけしか取得できませんでした。 すべてのデータを正しく取得するにはどのようにしたらよいのでしょうか?

  • C言語の構造体のサイズについて

    いつもお世話になっていります。 早速ですが、C言語の構造体のサイズについて教えてください。 typedef struct B { short code; char name; float price; } B; typedef struct A { B bbb[10]; double sougaku; } A; A aaa; といった構造体があった場合に、 sizeof(aaa.bbb.code) + sizeof(aaa.bbb.name) + … + sizeof(aaa.sougaku) という風に一つ一つサイズを取得し、合計して構造体のサイズを取得した場合と sizeof(aaa) という風に構造体のサイズを取得した場合のサイズの値が異なるといった現象が起きます。 その原因が分からなくて困っております。 そこで考えられる要因をお教えください。 因みに実際の構造体はサイズで言えば2500バイトくらいあります。 froat/char/double/short 型を使用しております。 よろしくお願いします。

  • C言語、エラーメッセージが紐解けません。

    いつも大変お世話になり誠にありがとうございます。 標記の件。 エラーメッセージが紐解けません。 どうかどなたかアドバイスください。 下記にコードとコンパイルエラーを書きます。        記 コード #include <stdio.h> typedef struct Car{ int num; double gas; }Car; int main(void) { printf("int型のサイズは%dバイトです。\n", sizeof(int)); printf("double型のサイズは%dバイトです。\n", sizeof(double)); printf("構造体struct Car型のサイズは%dバイトです。\n",sizeof(Car)); printf("構造体struct Car型へのポインタのサイズは%dバイトです。\n",sizeof(Car *)); return 0; } コンパイラーエラー C:\MinGW>gcc text20.c -o text20 text20.c: In function 'main': text20.c:12:11: warning: unknown escape sequence: '\221' printf("構造体struct Car型のサイズは%dバイトです。\n",sizeof(Car)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ text20.c:13:11: warning: unknown escape sequence: '\221' printf("構造体struct Car型へのポインタのサイズは%dバイトです。\n",sizeof(Car *)); 以上です。 ご多忙中恐れ入ります。 ご回答の程宜しくお願い申し上げます。

  • OVERLAPPED構造体が分かりません・・。

    シリアルポートで非同期データ通信するプログラム作成初歩段階です。 ReadFileの第5引数にはOVERLAPPED構造体へのポインタを指定することは分かったのですが。この構造体の各メンバにどんな値を入れたらいいのか分りません・・・。 よろしくお願いします。 typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hEvent; } OVERLAPPED;

  • 共有メモリへのマッピング(MapViewOfFile)について

    共有メモリについて(特にMapViewOffileについて)教えてください。 ある構造体と、あるデータAを共有メモリへマッピングしたい考えています。 構造体は、 typedef struct _Data { int length; long data; char mIntArrayData[256]; } Data; データAは、short型の配列(要素数はx*y*z,x,y,zはcsvファイル等から読み込む)で、サイズをdatasize = sizeof(short) * x * y * z;とします。 この2つを使って、 両方のデータを long AllDataSize = sizeof(Data) + datasizeとしました。 このサイズを使って、共有メモリのマップハンドルを hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,PAGE_READWRITE,AllDataSize,MAPPED_FILE_NAME); (MAPPED_FILE_NAMEは、 メモリマップドファイルの名前) で、生成しました。 生成はできたのですが、データAにアクセスするための下記のような時にマッピングに失敗してしまいました。 DWORD dwOffset = sizeof(DATA); short *pData = (short *)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, dwOffset, Bytes); (Bytesはマッピングしたいバイト数でsizeof(short)の倍数) 次のようなDATAにアクセスするマッピングには成功しています。 DWORD dwOffset = 0; DATA *pDATA = (DATA *)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, dwOffset, sizeof(DATA)); 色々なサイト等を調べて、考えてみたのですが、怪しいところはdwOffsetと、CreateFileMappingで、マッピングしたい全体のファイルサイズを、構造体とデータAのサイズの単純な足し算としているところと考えています。ただ、はっきりとした答えが全くわからないので、どうか御教授お願いします。

  • CStringWが 使えないので

    マルチバイト(Shift-JIS)を 使っているソースで                                                                                             DWORD   size;   CStringW   csw;;   csw =   filename;    size = csw.GetLength(); というコードで size の値は 以下のコードの  sizeと同じ値になりますか?                    DWORD size; CString cs; cs = filename; size = cs.GetLength() * sizeof(TCHAR); 表題にも書きましたが CStringW が、使えないので 宜しく お願い致します。                       

  • 汎用のファイル読み取り関数について

    ファイルデータを読み取る関数を作成しています. Data *ReadFile (const char *name, Data *data, const char *format, ...) というプロトタイプを考えます. ここでDataはプログラマが自由に定義できる構造体です. この構造体の一例を示すと, typedef struct { int id; /* ID番号 */ char name[32]; /* 氏名 */ char sex; /* 性別 */ int age; /* 年齢 */ char addr[64]; /* 住所 */ } Data; という具合です. 読み取るファイルの書式はプログラムの種類によって 異なりますが, fopen関数やfclose関数を使用するといった 手順は全く同一です. そこで上記のような汎用的な ファイル読み取り関数を書こうと思ったのですが 読み取り部分fscanfの処理をどのように行えばよいか 分かりません. formatで指定する書式は'%'を区切りとする複数の文字列に 分け(例えばformat="%s %d"であればbuffer="%s \0%d\0"), char型のポインタ配列bpで参照できます. 可変引数の部分で 構造体のメンバを指定できるようにしたいのですが... ちなみに呼出側では Data *data; data = ReadFile ("a.txt", data, "%d %s %c %d %s", data->id, ...); というようにしたいと考えています. ソースを以下に示します. どなたかお力をお貸しくださいませ. Data *ReadFile (const char *name, Data *data, const char *format, ...){ FILE *stream; size_t data_size = 1024, buffer_size = 128, bp_size = 16; short i, j, k; char *buffer; char **bp; /* buffer pointer */ va_list ap; /* argument pointer */ (省略) va_start (ap, format); i = 0; k = 0; while (!feof (stream)) { fscanf (stream, bp[i], va_arg (ap, ????)); (省略) } va_end (ap); }

  • 構造体をファイルに出力できません

    はじめまして、お世話になります。 『ダイアログで取得したファイル名』を、含むData構造体をファイルとして書き込む場合に限り、ファイルが出力されません。 Data構造体の文字列file_nameが『ダイアログで取得したファイル名』でなければ正常に出力されます。また、関数の返値や書き込み後のFILE構造体の中身を読み込んで調べたりしましたが、見る限りエラーはありませんでした。 開発ツールはMicrosoft Visual Studio 2005を使用しています。 どうか皆さんの知恵を貸してください! お願いします! //ファイルとして出力する構造体 typedef struct { TCHAR file_name[256]; BYTE id; }Data; //ファイルを開くダイアログ void OpenFile(HWND hWnd, TCHAR file_name[]) { OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = TEXT("png files {*.bmp}\0*.bmp\0") TEXT("all files {*.*}\0*.*\0\0"); ofn.lpstrFileTitle = (LPWSTR)file_name; ofn.nMaxFileTitle = CHAR_SIZE; ofn.lpstrFile = NULL; ofn.Flags = OFN_FILEMUSTEXIST; GetOpenFileName(&ofn); } //ファイルを書き込む void SaveData(Data save_file[]) { FILE *file; errno_t err; size_t write_num; //書き込む err = _tfopen_s(&file, TEXT("hoge.map"), TEXT("w+b")); if(err != 0) return; write_num = fwrite(save_file, sizeof(Data), 6, file); //きちんと書き込めているか確かめる Data chek_data[6]; fseek(file, 0L, SEEK_SET); fread(chek_data, sizeof(Data), 6, file); fclose(file); }

専門家に質問してみよう