ReadFile

https://msdn.microsoft.com/ja-jp/library/ms740506.aspx https://msdn.microsoft.com/ja-jp/library/ms737526.aspx https://msdn.microsoft.com/ja-jp/library/cc429130.aspx https://msdn.microsoft.com/ja-jp/library/ms684342.aspx https://msdn.microsoft.com/ja-jp/library/cc428944.aspx https://msdn.microsoft.com/ja-jp/library/cc428944.aspx https://msdn.microsoft.com/ja-jp/library/cc430204.aspx https://msdn.microsoft.com/ja-jp/library/cc428944.aspx https://msdn.microsoft.com/ja-jp/library/cc430074.aspx https://msdn.microsoft.com/ja-jp/library/aa363190.aspx https://msdn.microsoft.com/ja-jp/library/cc429057.aspx https://msdn.microsoft.com/ja-jp/library/ms684342.aspx https://msdn.microsoft.com/ja-jp/library/cc428987.aspx https://msdn.microsoft.com/ja-jp/library/cc429130.aspx https://msdn.microsoft.com/ja-jp/library/ms684342.aspx https://msdn.microsoft.com/ja-jp/library/cc430074.aspx https://msdn.microsoft.com/ja-jp/library/cc428987.aspx

ファイルからデータを読み取ります。ファイルポインタの現在の位置が、読み取りの開始位置になります。読み取りが完了すると、ファイルポインタの位置は、実際に読み取ったバイト数だけ進みます。ただし、オーバーラップ I/O(非同期 I/O)を指定してファイルのハンドルを作成した場合は、読み取り操作が完了した後、アプリケーション側でファイルポインタを調整してください。

この関数は、同期と非同期両方の操作を想定して設計されています。一方、ReadFileEx 関数は、非同期操作専用に設計されています。そして、アプリケーションはファイルの読み取り操作を行っている間に、他の処理を実行できます。

BOOL ReadFile(
  HANDLE hFile,                // ファイルのハンドル
  LPVOID lpBuffer,             // データバッファ
  DWORD nNumberOfBytesToRead,  // 読み取り対象のバイト数
  LPDWORD lpNumberOfBytesRead, // 読み取ったバイト数
  LPOVERLAPPED lpOverlapped    // オーバーラップ構造体のバッファ
);

パラメータ

hFile
読み取り対象のファイルのハンドルを指定します。このハンドルは、GENERIC_READ アクセス権を指定して作成したものでなければなりません。

Windows NT/2000:非同期の読み取り操作を行う場合、FILE_FLAG_OVERLAPPED フラグを指定し CreateFile 関数を呼び出して開いた任意のハンドル、または と どちらかの関数が返したソケットのハンドルを指定します。

Windows 95/98:非同期の読み取り操作を行う場合、FILE_FLAG_OVERLAPPED フラグを指定し CreateFile 関数を呼び出して開いた通信リソース、または socket accept どちらかの関数が返したソケットのハンドルを指定します。メールスロット、名前付きパイプ、ディスクファイルに対する非同期読み取り操作はサポートしていません。

lpBuffer
1 個のバッファへのポインタを指定します。関数から制御が返ると、このバッファに、ファイルから読み取ったデータが格納されます。
nNumberOfBytesToRead
読み取り対象のバイト数を指定します。
lpNumberOfBytesRead
1 個の変数へのポインタを指定します。関数から制御が返ると、この変数に、実際に読み取ったバイト数が格納されます。何らかの作業やエラーのチェックを行う前に、ReadFile はこの値を 0 に設定します。名前付きパイプに対してこの関数を実行し、戻り値が 0 以外(TRUE)である場合に、この変数に値 0 が格納されたときは、メッセージモードのパイプのもう一方の側が、nNumberOfBytesToWrite パラメータを 0 に設定して WriteFile 関数を呼び出した(つまり、何も書き込まずに、ファイルのタイムスタンプを更新しただけ)ことを意味します。

Windows NT/2000:lpOverlapped パラメータで NULL を指定した場合、lpNumberOfBytesRead パラメータで NULL を指定できません。lpOverlapped パラメータで有効なポインタを指定した場合、lpNumberOfBytesRead パラメータで NULL を指定できます。オーバーラップ読み取り操作を行う場合、 関数を呼び出すと、読み取りの終わったバイト数を取得できます。hFile が I/O 完了ポート(詳細については、MSDN ライブラリで「I/O completion ports」を参照してください)に関連付けられている場合、GetQueuedCompletionStatus 関数を呼び出すと、読み取りの終わったバイト数を取得できます。

Windows 95/98:このパラメータでは NULL を指定できません。

lpOverlapped
1 個の 構造体へのポインタを指定します。hFile パラメータが、FILE_FLAG_OVERLAPPED を指定して作成したファイルのハンドルを指している場合、この構造体は必須です。

hFile パラメータが、FILE_FLAG_OVERLAPPED フラグを指定して開かれたハンドルを指している場合、lpOverlapped パラメータでは NULL を指定できません。このパラメータでは、1 個の有効な OVERLAPPED 構造体を指定しなければなりません。もしこの状況で、lpOverlapped パラメータで NULL を指定すると、この関数は、読み取り操作が完了したと間違って通知することがあります。

hFile パラメータが、FILE_FLAG_OVERLAPPED フラグを指定して開かれたハンドルを指していて、lpOverlapped パラメータで有効なポインタを指定した場合、OVERLAPPED 構造体で指定したオフセットでファイルの非同期読み取りが開始され、ReadFile はファイルの読み取りが完了する前に制御を返すことがあります。この場合、ReadFile 関数は 0(FALSE)を返し、GetLastError 関数は ERROR_IO_PENDING を返します。この結果、呼び出し側プロセスは読み取り操作が完了する前に、他の作業を実行できます。その後、読み取り操作が完了すると、OVERLAPPED 構造体で指定したイベントがシグナル状態になります。

hFile パラメータが、FILE_FLAG_OVERLAPPED フラグを指定せずに開かれたハンドルを指していて、lpOverlapped パラメータで NULL を指定した場合、ファイルポインタの現在の位置からファイルの同期読み取りが開始され、ReadFile は、読み取りが完了すると制御を返します。

Windows NT/2000:hFile パラメータが、FILE_FLAG_OVERLAPPED フラグを指定せずに開かれたハンドルを指していて、lpOverlapped パラメータで有効なポインタを指定した場合、OVERLAPPED 構造体で指定したオフセットでファイルの同期読み取りが開始され、ReadFile は、読み取りが完了すると制御を返します。

Windows 95/98:ファイル、ディスク、パイプ、メールスロットのいずれかを対象とする操作では、このパラメータで NULL を指定しなければなりません。OVERLAPPED 構造体へのポインタを指定すると、この関数は失敗します。ただし、Windows 95/98 は、シリアルポートとパラレルポートに対するオーバーラップ I/O をサポートしています。

戻り値

ReadFile 関数は、次のいずれかが成立すると制御を返します。パイプの書き込み側で書き込みが完了するか、指定されたバイト数の読み取りが終わるか、エラーが発生した場合です。

関数が成功すると、0 以外の値が返ります。

戻り値が 0 以外で、実際に読み取ったバイト数が 0 の場合、読み取り操作を開始する時点でファイルポインタがファイルの終わり(EOF)を超えていたことを示します。ただし、FILE_FLAG_OVERLAPPED フラグを指定してファイルを開いていた場合、lpOverlapped パラメータに NULL 以外の値を指定すると、戻り値は 0(FALSE)になります。このとき、ファイルポインタがファイルの終わりを超えていると、 関数は ERROR_HANDLE_EOF を返します。

関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、 関数を使います。

解説

ほかのプロセスによってロック(排他ロック)されている領域を読み取ろうとすると、この関数は失敗します。

FILE_FLAG_NO_BUFFERING フラグを指定してファイルを開いた後、そのファイルの作業を行う場合、アプリケーションは次の各要件を満たさなければなりません。

•ファイルアクセスは、ボリュームのセクタサイズの整数倍のバイトオフセットの位置で開始しなければなりません。ボリュームのセクタサイズを判断するには、GetDiskFreeSpace 関数を呼び出します。

•ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければなりません。たとえば、セクタサイズが 512 バイトの場合、512 バイト、1,024 バイト、2,048 バイトの読み書きはできますが、335 バイト、981 バイト、7,171 バイトなどの読み書きはできません。

•読み書き操作用のバッファのアドレス(メモリ内のアドレス)を、ボリュームのセクタサイズの整数倍に整列(セクタ整列)させなければなりません。バッファをセクタ整列させる 1 つの方法は、 関数を使ってバッファを割り当てることです。VirtualAlloc 関数が割り当てるメモリは、システムのページサイズの整数倍のアドレスに整列されています。ページサイズとボリュームのセクタサイズは両方とも 2 のべき乗なので、システムのページサイズの整数倍に整列されたメモリは、ボリュームのセクタサイズの整数倍のアドレスにも整列されます。

入力バッファを使って読み取り操作を行っている間にそのバッファにアクセスすると、そのバッファ内に読み込んだデータが壊れることがあります。読み取り操作が完了するまでは、アプリケーションは入力バッファの読み取り、書き込み、再割り当て、解放を行ってはなりません。

コンソール入力のハンドルを指定して ReadFile 関数を実行すると、コンソール入力バッファから文字を読み取ることができます。コンソールのモードは、この関数の正確な動作を決定します。

名前付きパイプからデータをメッセージモードで読み取っているとき、次のメッセージが nNumberOfBytesToRead パラメータで指定した値より長い場合、ReadFile 関数は 0(FALSE)を返し、 関数は ERROR_MORE_DATA を返します。その後、ReadFile または 関数を呼び出すと、メッセージの残りの部分を読み取れます。

通信デバイスからデータを読み取っているとき、ReadFile 関数の動作は、現在の通信タイムアウト値の影響を受けます。SetCommTimeoutsGetCommTimeouts の各関数は、この通信タイムアウト値の設定と取得を行います。タイムアウト値の設定を怠ると、予測できない結果が生じることがあります。通信タイムアウトの詳細については、MSDN ライブラリの「」構造体を参照してください。

メールスロットからデータを読み取っているとき、バッファが小さすぎると、ReadFile 関数は 0(FALSE)を返し、GetLastError 関数は ERROR_INSUFFICIENT_BUFFER を返します。

名前なしパイプの書き込みハンドルを閉じた後、対応する読み取りハンドルを使ってパイプからデータを読み取ろうとすると、ReadFile 関数は 0(FALSE)を返し、GetLastError 関数は ERROR_BROKEN_PIPE を返します。

未処理の非同期 I/O 要求が大量に残っているとき、ReadFile 関数は失敗することがあります。このような障害が発生した場合、GetLastError 関数は、ERROR_INVALID_USER_BUFFER または ERROR_NOT_ENOUGH_MEMORY を返すことがあります。

同期と非同期のどちらで読み取り操作を行うかによって、ReadFile 関数でファイルの終わり(EOF)の条件を判定する方法が異なります。

同期の読み取り操作を行っていて、ファイルの終わりに達した場合、ReadFile 関数は 0 以外の値(TRUE)を返し、*lpNumberOfBytesRead を 0 に設定します。次のサンプルコードは、非同期の読み取り操作で、ファイルの終わりに達したかどうかを判定します。

// 同期の読み取り操作を行おうとする。

bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ;

// ファイルの終わりをチェックする。

if (bResult && nBytesRead == 0,)

{

    // ファイルの終わりに達した。

}

非同期の読み取り操作を行った場合、ReadFile 関数を最初に呼び出した際にファイルの終わりに達することも、それに続けて非同期の操作を行った際にファイルの終わりに達することもあります。

ReadFile 関数を呼び出して非同期の読み取り操作を行った際に EOF を検出した場合、ReadFile 関数は 0(FALSE)を返し、GetLastError 関数は ERROR_HANDLE_EOF を返します。

それ以降の非同期操作で EOF を検出した場合、GetOverlappedResult 関数を呼び出して、その操作が 0(FALSE)を返したかどうかを判断してください。 関数を呼び出して、 構造体の hEvent メンバを設定しておくと、GetLastError が ERROR_HANDLE_EOF を返したかどうかを判断することもできます。

未処理のすべての非同期 I/O 操作を取り消すには、CancelIo 関数を使います。この関数は、指定されたファイルハンドルに対して呼び出し側プロセスが発行した操作だけを取り消します。取り消された各 I/O 操作は、ERROR_OPERATION_ABORTED エラーを返して終了します。

フロッピーディスクが入っていないフロッピーディスクドライブの読み取りを行おうとすると、システムはユーザーに対して、操作を再試行するかどうか尋ねるメッセージボックスを表示します。このメッセージボックスの表示を回避するには、SEM_NOOPENFILEERRORBOX を指定して 関数を呼び出してください。

次のサンプルコードは、非同期の読み取り操作でファイルの終わりに達したかどうかを判定する方法を示します。

// オーバーラップ構造体のメンバの値を設定する。

gOverLapped.Offset     = 0;

gOverLapped.OffsetHigh = 0;

gOverLapped.hEvent     = hEvent;

// 非同期の読み取り操作を行おうとする。

bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,

    &gOverlapped) ;

// 問題が発生した場合、または非同期の操作が未処理のままになっている場合

if (!bResult)

{

    // エラーコードに基づいて処理を行う。

    switch (dwError = GetLastError())

    {

        case ERROR_HANDLE_EOF:

        {

            // ReadFile を呼び出した際に

            // ファイルの終わりに達した。

            // そのことに対処するコード

        }

        case ERROR_IO_PENDING:

        {

            // 非同期 I/O は依然として進行中である。

            // この間に、何かほかの作業を実行する。

            GoDoSomethingElse() ;

            // 非同期読み取り操作の結果をチェックする。

            bResult = GetOverlappedResult(hFile, &gOverlapped,

                &nBytesRead, FALSE) ;

            // 何か問題があった場合

            if (!bResult)

            {

                // エラーコードに基づいて処理を行う。

                switch (dwError = GetLastError())

                {

                    case ERROR_HANDLE_EOF:

                    {

                        // 非同期の操作を行っている最中に

                        // ファイルの終わりに達した。

                    }

                    // 他のエラーが発生した場合、それに対処する。

                }

            }

        } // case 構造の終わり

        // 他のエラーが発生した場合、それに対処する。

    } // switch 構造の終わり

} // if 構造の終わり

MAPI:詳細については、MSDN ライブラリの「」を参照してください。

対応情報

Windows NT/2000:Windows NT 3.1 以降
Windows 95/98:Windows 95 以降
ヘッダー:Winbase.h 内で宣言、Windows.h をインクルード
インポートライブラリ:Kernel32.lib を使用

参照

CancelIo, CreateFile, GetCommTimeouts, , GetQueuedCompletionStatus, , , ReadFileEx, SetCommTimeouts, , WriteFile

表示: