バイナリーデータを区切って読込む

[戻る]
ピースケ 2006/07/21(金) 11:16:41
256バイトの固定でバイナリーファイルを読む事ができたので
可変で出来るようにします。

読込むファイルのデータのバイト数 528

HANDLE  hF;        // ファイルのハンドル
DWORD dwResult;        // 読み取ったバイト数
char chBuf[1024];        // バイナリーデータ格納領域
int value;         // バイト数格納

hF = CreateFile(FilePath,GENERIC_READ,0,NULL,OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,NULL);

ReadFile(hF, chBuf, value = GetFileSize(hF , NULL), &dwResult, NULL);

結果
  value は528と期待値が入っているのでOK

これを 0〜256, 257〜512, 513〜528 と256づつ読み込みたい場合の方法が分りません。
ReadFileは先頭からしか取れないのでしょうか?(例えば 257バイト目から256バイト読
込む事が出来ないのか)
どなたか教えて下さい。よろしくお願い致します。

Blue 2006/07/21(金) 11:23:15
>0〜256, 257〜512, 513〜528 と256づつ読み込みたい場合の方法が分りません。
ReadFileのヘルプに
>読み取りが完了すると、ファイルポインタの位置は、実際に読み取ったバイト数だけ
>進みます。
とありますけど、確認してみましたか?


質問する前に、まずはヘルプをみて、簡単なコードを試してみてください。

ピースケ 2006/07/21(金) 13:28:32
Blueさんありがとうございます。

ファイルを2回開くしかやり方が無いでしょうか?
最初の256バイトは読込む必要が無いので、257バイトから256づつデータを
読込む処理をしたいです。

私自身のやり方だと無駄が多くなってしまいます。
効率のいいやり方などご教授お願いします。

<サンプル>
memset(chBuf,'\0',sizeof(chBuf)); // 初期化
// ファイルを開く(全体のファイルサイズを取得する為)
hF = CreateFile(FilePath,GENERIC_READ,0,NULL,OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,NULL);
    
if (hF == INVALID_HANDLE_VALUE)
{
 return 1;
}

// データを読み込む(全体のファイルサイズを取得)
ReadFile(hF, chBuf, nNumOfByte = GetFileSize(hF , NULL), &dwResult, NULL);
// ファイルを閉じる
CloseHandle(hF);
    
//ファイルを開く(257バイト目から256バイト取得する為)
hF = CreateFile(FilePath,GENERIC_READ,0,NULL,OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,NULL);
    
if (hF == INVALID_HANDLE_VALUE)
{
 return 1;
}
for(count = 0; count< 4; count++)
{
 memset(chBuf,'\0',sizeof(chBuf)); // 初期化

 //この場合は頭からとっていくので本来は257バイトから256づつとりたい
 ReadFile(hF, chBuf, 256, &dwResult, NULL);
}
// ファイルを閉じる
CloseHandle(hF);

PATIO 2006/07/21(金) 13:34:19
> ファイルを2回開くしかやり方が無いでしょうか?
そうではなくて一回開いてReadを二回するのです。
ファイルのOpenは処理としては重い処理なので開きっぱなしで
支障が無い場合は開きっぱなしにするのが普通です。
あと、閉じてしまうとファイルポインタはファイルの先頭に戻るので
読み込み開始位置に設定しないと駄目になります。
通常は、

1.ファイルをOpen

2.ファイルからRead

3.読んだデータで処理。

4.ファイルエンドで無いなら2に戻る。

5.ファイルをClose

とすると思いますよ。

PATIO 2006/07/21(金) 13:36:14
がーっ、誤字。

誤)
> 読み込み開始位置に設定しないと駄目になります。

正)
読み込み開始位置をきちんと設定しないと駄目になります。

Blue 2006/07/21(金) 13:41:07
> 最初の256バイトは読込む必要が無いので、257バイトから256づつデータを
> 読込む処理をしたいです。
普通に読み捨てればいいだけなのでは?

// ファイルを開く
hF = CreateFile(FilePath,GENERIC_READ,0,NULL,OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,NULL);
if (hF == INVALID_HANDLE_VALUE)
{
    return 1;
}

// 全体のファイルサイズを取得
nNumOfByte = GetFileSize(hF , NULL);
// ファイルサイズのチェック
if ( nNumOfByte != 528 )
{
    return 1;
}

// 先頭256バイト読み捨て
ReadFile( hF, chBuf, 256, &dwResult, NULL );

// 257バイトから256取得
memset( chBuf, '\0', sizeof( chBuf ) );
ReadFile( hF, chBuf, 256, &dwResult, NULL );



また、SetFilePointerという関数があります。この関数はファイルの位置移動してくれ
ます。(詳しくはヘルプで)


ちなみに、MFCを使うのであれば、CFileクラスを使ったほうが見やすくなると思いま
す。

Blue 2006/07/21(金) 14:18:26
CloseHandleが抜けている箇所がありました。

// ファイルサイズのチェック
if ( nNumOfByte != 528 )
{
    CloseHAndle(hF);
    return 1;
}

ピースケ 2006/07/21(金) 14:37:19
2回読込んだのは1回目の
ReadFile(hF, chBuf, nNumOfByte = GetFileSize(hF , NULL), &dwResult, NULL);
でファイルの最後まで読込んでいるので
2回目の
ReadFile(hF, chBuf, 256, &dwResult, NULL);
ではファイルポインターが最後の場所をさしているのでデータを読んでくれませんでし
た。

SetFilePointer(hF , 256 , NULL , FILE_CURRENT);
ファイルポインターを256番目を指すようにしてるつもりですが

ReadFile(hF, chBuf, 256, &dwResult, NULL);
データが何もはいってこないのはなぜでしょうか?

<参考HP>
http://72.14.235.104/search?
q=cache:M5tNjtXANtoJ:wisdom.sakura.ne.jp/system/winapi/win32/win113.html+SetFil
ePointer&hl=ja&gl=jp&ct=clnk&cd=4&lr=lang_ja

YuO [E-Mail] 2006/07/21(金) 14:57:54
> SetFilePointer(hF , 256 , NULL , FILE_CURRENT);
> ファイルポインターを256番目を指すようにしてるつもりですが

どこがでしょうか。
FILE_CURRENTの意味はちゃんとわかっていますか?
see) http://msdn.microsoft.com/en-us/fileio/fs/setfilepointer.asp

そもそも,全体を読み込む行為に意味はあるのですか?


> <参考HP>

何のためにわざわざGoogleキャッシュのURIを書いているんだか……。

yoh2 [E-Mail] 2006/07/22(土) 07:26:41
全ファイルを一度に読み込めるほどバッファサイズを大きくとれるorファイル
サイズが小さいなら、発想を変えて、全て読み込んだバッファを256バイトずつ
読むようにするという手も。
その際はくれぐれもバッファオーバーランにご注意を。

# それでも、今後のためにファイルの読み書き位置設定方法はしっかり
# 覚えておくべきでしょうけど。

ピースケ 2006/07/25(火) 11:02:31
[[解決]]
返事遅れて済みません

みなさんありがとうございます。
このような形でやりました。

READ_DATA_SIZE        256

char chBuf[READ_DATA_SIZE];
//ファイルを開く
hF = CreateFile(FilePath,GENERIC_READ,0,NULL,OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,NULL);

 if (hF == INVALID_HANDLE_VALUE)
 {
  return 1;
 }

 SetFilePointer(hF , 256 , NULL , FILE_CURRENT); // 最初の256バイトは進める

 // 256バイト読込む
 ReadFile(hF, chBuf, sizeof(chBuf), &dwResult, NULL);

三草 2006/07/25(火) 12:20:11
ごめんなさい、ご回答ではなく単なる赤ペン先生になってしまいますが、
補足とご参考までに。。。

// マジックナンバーや即値はなるべく避けましょう
#define READ_DATA_SIZE    256
#define READ_START_POINT  256
#define FILE_OPEN_ERROR   1
・・・

// # NULL分入れておくとよろしいかと
char chBuf[READ_DATA_SIZE + 1];

//ファイルを開く
hF = CreateFile(FilePath,GENERIC_READ,0,NULL,OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,NULL);

if (hF == INVALID_HANDLE_VALUE){
    return FILE_OPEN_ERROR;
}

// 最初の256バイトは進める
// # 256バイト目から読み込ませるため、ポインタ移動する
SetFilePointer( hF, READ_START_POINT, NULL, FILE_BEGIN);
// ##「最初」から256バイト進める。ならこれ↑^^^^^^^^^^
// ## FILE_CURRENT だと、ファイルを開いた直後は「たまたま」最初を指しているで
// ## ピースケさんのイメージどおりに動いています。
// ## 仮に、ファイル開いた直後に、nバイト読み込む処理が入ってしまったら、
// ## FILE_CURRENT だと、n+256バイト目を指すことになります。(それで良いなら良い
のですが)

// 256バイト読込む
ReadFile(hF, chBuf, sizeof(chBuf), &dwResult, NULL);
// # ReadFileを「安全」に行うのであれば、第3引数はsizeof(chBuf)で良いと思います
// # ですが、そうするとコメントとコードが合わないので、コメントにあわせるなら、
// # ReadFile(hF, chBuf, READ_DATA_SIZE, &dwResult, NULL);
// ## でも組む人の思想によって、READ_DATA_SIZEとするか、sizeof(chBuf)とするか
// ## 分かれるかもしれません。

ピースケ 2006/07/25(火) 16:05:52
三草さんありがとうございます。
赤ペン先生大変為になります。

またよろしくお願い致します。

古いスレッドには追加発言できません。