ReadFileにてファイルの同期読み込みを行うとき、
> 戻り値が 0 以外で、実際に読み取ったバイト数が 0 の場合、読み取り操作を開始する時点でファイルポインタがファイルの終わり(EOF)を超えていたことを示します。
これは分かるのですが、
> 同期の読み取り操作を行っていて、ファイルの終わりに達した場合、ReadFile 関数は 0 以外の値(TRUE)を返し、*lpNumberOfBytesRead を 0 に設定します。
これはつまり、同期の読み取り操作を行っていてファイルの終わりに達した場合はどれだけ、読み込んだのか分からないということになりますよね。
だから例えば、ファイルをサイズのチェックもせずにただひたすら先頭から末尾まで読み込んでいくようなプログラムは、最後に読み込んだデータのどこまでを使っていいのか分からなくなると思うのですが、ドキュメントの解釈あってるでしょうか?
MSDN
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpfileio/html/_win32_readfile.asp
なんで日本語版がそのような記述になっているのかはわかりませんが,英語版にそのような記述はありません。
http://msdn.microsoft.com/library/en-us/fileio/fs/readfile.asp
*lpNubmerOfBytesReadが0を返した時点で読み取り終了でよいことになります。
YuOさん、レスありがとうございます。
上の引用に対応する英語版のドキュメントは
> If the return value is nonzero and the number of bytes read is 0 (zero), the file pointer is beyond the current end of the file at the time of the read operation.
と
> When a synchronous read operation reaches the end of a file, ReadFile returns TRUE and sets *lpNumberOfBytesRead to 0 (zero).
になると思いますが、日本語版と同じ意味だと思うのですが...う〜ん、英語にそれほど自信はないですけど、間違ってますでしょうか?
まあ実験すればわかる話なのではあるが
15 byte の「普通のファイル」を 10 byte づつ読み込むと
1回目:10 2回目:5 3回目:0
となるわけだ。いずれも ReadFile の返却値は非0
pipe や Comm などだと違う結果になりうるよん
tetrapodさん、レスありがとうございます。
さっそく今、下記のプログラムを実行してみたところ
int _tmain(int argc,LPCTSTR argv[])
{
::_tsetlocale(LC_ALL,_T(""));
HANDLE hFile;
//開く
if((hFile=::CreateFile(
_T("test.data"), //テスト用ファイル(先頭から0x01,0x02...0x09と9byteデータが入っている)
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
::_putts(_T("Failed to open the file."));
return 0;
}
//読み込む
DWORD data;
DWORD bytesRead;
BOOL result;
DWORD errorCode;
for(unsigned int count=0;count<4;count++)
{
result =::ReadFile(
hFile,
&data,
sizeof(data),
&bytesRead,
NULL
);
errorCode =::GetLastError();
::_tprintf(
_T("-------------------------\n")
_T("data :%#010x\n")
_T("bytesRead :%u\n")
_T("result :%s\n")
_T("errorCode :%u\n"),
data,
bytesRead,
(result == TRUE)?_T("TRUE"):_T("FALSE"),
errorCode
);
}
//閉じる
::CloseHandle(hFile);
return 0;
}
実行結果は
-------------------------
data :0x04030201
bytesRead :4
result :TRUE
errorCode :0
-------------------------
data :0x08070605
bytesRead :4
result :TRUE
errorCode :0
-------------------------
data :0x08070609
bytesRead :1
result :TRUE
errorCode :0
-------------------------
data :0x08070609
bytesRead :0
result :TRUE
errorCode :0
となりました。
ドキュメントに書いてあるわけではありませんが、
(戻り値がTRUE) && (*lpNumberOfBytesRead < nNumberOfBytesToRead)で
ファイルが終端に達した。*lpNumberOfBytesReadに実際に読み取れたバイト数が入る。
(戻り値がTRUE) && (*lpNumberOfBytesRead == 0)で
すでに終端に達している、もしくは超えている。
という解釈でいこうと思います。
YuOさん,tetrapodさん
ありがとうございました。
ツイート | ![]() |