WriteFile 関数 (fileapi.h)

指定したファイルまたは入出力 (I/O) デバイスにデータを書き込みます。

この関数は、同期操作と非同期操作の両方向けに設計されています。 非同期操作専用に設計された同様の関数については、「 WriteFileEx」を参照してください。

構文

BOOL WriteFile(
  [in]                HANDLE       hFile,
  [in]                LPCVOID      lpBuffer,
  [in]                DWORD        nNumberOfBytesToWrite,
  [out, optional]     LPDWORD      lpNumberOfBytesWritten,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);

パラメーター

[in] hFile

ファイルまたは I/O デバイスへのハンドル (ファイル、ファイル ストリーム、物理ディスク、ボリューム、コンソール バッファー、テープ ドライブ、ソケット、通信リソース、mailslot、パイプなど)。

hFile パラメーターは、書き込みアクセス権を使用して作成されている必要があります。 詳細については、「 汎用アクセス権 」および「 ファイル セキュリティとアクセス権」を参照してください。

非同期書き込み操作の場合、hFile は、FILE_FLAG_OVERLAPPED フラグまたはソケットまたは accept 関数によって返されるソケット ハンドルを使用して、CreateFile 関数で開かれた任意のハンドルにすることができます。

[in] lpBuffer

ファイルまたはデバイスに書き込まれるデータを含むバッファーへのポインター。

このバッファーは、書き込み操作の間は有効なままである必要があります。 書き込み操作が完了するまで、呼び出し元はこのバッファーを使用しないでください。

[in] nNumberOfBytesToWrite

ファイルまたはデバイスに書き込まれるバイト数。

値 0 は、null 書き込み操作を指定します。 null 書き込み操作の動作は、基になるファイル システムまたは通信テクノロジによって異なります。

Windows Server 2003 および Windows XP: ネットワーク全体のパイプ書き込み操作のサイズは、書き込みごとに制限されます。 金額はプラットフォームごとに異なります。 x86 プラットフォームの場合、63.97 MB です。 x64 プラットフォームの場合は 31.97 MB です。 Itanium の場合は 63.95 MB です。 パイプの詳細については、「解説」セクションを参照してください。

[out, optional] lpNumberOfBytesWritten

同期 hFile パラメーターを使用するときに書き込まれたバイト数を受け取る変数へのポインター。 WriteFile は 、作業またはエラー チェックを実行する前に、この値を 0 に設定します。 このパラメーターが非同期操作の場合は NULL を 使用して、誤った結果が発生する可能性を回避します。

このパラメーターは、lpOverlapped パラメーターが NULL でない場合にのみ NULL にすることができます

Windows 7: このパラメーターを NULL にすることはできません。

詳細については、「解説」を参照してください。

[in, out, optional] lpOverlapped

hFile パラメーターが FILE_FLAG_OVERLAPPED で開かれた場合は、OVERLAPPED 構造体へのポインターが必要です。それ以外の場合は、このパラメーターを NULL にすることができます

バイト オフセットをサポートする hFile の場合、このパラメーターを使用する場合は、ファイルまたはデバイスへの書き込みを開始するバイト オフセットを指定する必要があります。 このオフセットは、OVERLAPPED 構造体の Offset メンバーと OffsetHigh メンバーを設定することによって指定されます。 バイト オフセットをサポートしていない hFile の場合、 OffsetOffsetHigh は無視されます。

ファイルの末尾に書き込むには、OVERLAPPED 構造体の Offset メンバーと OffsetHigh メンバーの両方を0xFFFFFFFFとして指定します。 これは、以前に CreateFile 関数を呼び出して、FILE_APPEND_DATA アクセスを使用して hFile を 開いた場合と機能的 同じです。

lpOverlappedFILE_FLAG_OVERLAPPEDのさまざまな組み合わせの詳細については、「解説」セクションと「同期とファイルの位置」セクションを参照してください。

戻り値

関数が成功した場合、戻り値は 0 以外 (TRUE) になります

関数が失敗した場合、または非同期的に完了している場合、戻り値は 0 (FALSE) になります。 エラーの詳細情報を得るには、GetLastError 関数を呼び出します。

メモGetLastError コード ERROR_IO_PENDINGは失敗ではありません。これは、書き込み操作が非同期的に完了待ちであることを指定します。 詳細については、「解説」を参照してください。
 

解説

WriteFile 関数は、次のいずれかの条件が発生すると を返します。

  • 要求されたバイト数が書き込まれます。
  • 読み取り操作では、パイプの読み取り側のバッファー領域が解放されます (書き込みがブロックされている場合)。 詳細については、「 パイプ 」セクションを参照してください。
  • 非同期ハンドルが使用されており、書き込みが非同期的に行われています。
  • エラーが発生しました。
WriteFile 関数は、未処理の非同期 I/O 要求が多すぎると、ERROR_INVALID_USER_BUFFERまたはERROR_NOT_ENOUGH_MEMORYで失敗することがあります。

保留中のすべての非同期 I/O 操作を取り消すには、次のいずれかを使用します。

  • CancelIo — この関数は、指定されたファイル ハンドルに対して呼び出し元スレッドによって発行された操作のみを取り消します。
  • CancelIoEx — この関数は、指定されたファイル ハンドルに対してスレッドによって発行されたすべての操作を取り消します。
CancelSynchronousIo 関数を使用して、保留中の同期 I/O 操作を取り消します。

取り消された I/O 操作は、エラー ERROR_OPERATION_ABORTEDで完了します。

WriteFile 関数は、ERROR_NOT_ENOUGH_QUOTAで失敗する可能性があります。つまり、呼び出し元のプロセスのバッファーをページ ロックできませんでした。 詳細については、「 SetProcessWorkingSetSize」を参照してください。

ファイルの一部が別のプロセスによってロックされていて、書き込み操作がロックされた部分と重複している場合、 WriteFile は失敗します。

ファイルに書き込む場合、書き込みに使用されるすべてのハンドルが閉じられるまで、最後の書き込み時刻は完全には更新されません。 したがって、最後の書き込み時刻を正確に保つには、ファイルへの書き込みの直後にファイル ハンドルを閉じます。

書き込み操作でバッファーを使用しているときに出力バッファーにアクセスすると、そのバッファーから書き込まれたデータが破損する可能性があります。 書き込み操作が完了するまで、書き込み操作で使用されている出力バッファーの書き込み、再割り当て、または解放は、アプリケーションで行う必要があります。 これは、非同期ファイル ハンドルを使用する場合に特に問題になる可能性があります。 同期と非同期のファイル ハンドルに関する追加情報については、「 同期とファイルの位置 」セクションと「 同期および非同期 I/O」で後ほど確認できます。

リモート ファイルのタイム スタンプが正しく更新されない場合があることに注意してください。 一貫性のある結果を得るには、バッファーなしの I/O を使用します。

システムは、書き込む 0 バイトを null 書き込み操作を指定すると解釈し、 WriteFile はファイルを切り捨てたり拡張したりしません。 ファイルを切り捨てたり拡張したりするには、 SetEndOfFile 関数を使用します。

WriteFile とコンソール出力へのハンドルを使用して、画面バッファーに文字を書き むことができます。 関数の正確な動作は、コンソール モードによって決まります。 データは現在のカーソル位置に書き込まれます。 書き込み操作後にカーソル位置が更新されます。 コンソール ハンドルの詳細については、「 CreateFile」を参照してください。

通信デバイスに書き込む場合、WriteFile の動作は、Set として現在の通信タイムアウトによって決定され、SetCommTimeouts 関数と GetCommTimeouts 関数を使用して取得されます。 タイムアウト値の設定に失敗すると、予期しない結果が発生する可能性があります。 通信タイムアウトの詳細については、「 COMMTIMEOUTS」を参照してください。

単一セクターの書き込みはアトミックですが、トランザクションを使用しない限り、複数セクターの書き込みはアトミックであるとは限りません (つまり、作成されたハンドルはトランザクション ハンドルです。たとえば、 CreateFileTransacted を使用して作成されたハンドル)。 キャッシュされた複数セクターの書き込みが、必ずしもすぐにディスクに書き込まれるとは限りません。そのため、CreateFileFILE_FLAG_WRITE_THROUGHを指定して、キャッシュの遅延が発生することなく、マルチセクター書き込み全体がディスクに書き込まれるようにします。

マウントされたファイル システムを持つボリュームに直接書き込む場合は、まずボリュームへの排他アクセス権を取得する必要があります。 そうしないと、アプリケーションの書き込みがファイル システムからの他の変更と競合し、ボリュームの内容が不整合な状態のままになる可能性があるため、データの破損やシステムが不安定になるリスクがあります。 これらの問題を回避するために、Windows Vista 以降で次の変更が行われています。

  • ボリュームにマウントされたファイル システムがない場合、または次のいずれかの条件が満たされている場合、ボリューム ハンドルの書き込みは成功します。
    • 書き込まれるセクターはブート セクターです。
    • 書き込まれるセクターは、ファイル システム領域の外部に存在します。
    • FSCTL_LOCK_VOLUMEまたはFSCTL_DISMOUNT_VOLUMEを使用して、ボリュームを明示的にロックまたはマウント解除しました。
    • ボリュームに実際のファイル システムがありません。 (言い換えると、RAW ファイル システムがマウントされています)。
  • 次のいずれかの条件に当てはまる場合、ディスク ハンドルへの書き込みは成功します。
    • 書き込まれるセクターは、ボリュームのエクステント内にありません。
    • マウントされたボリューム内に収まるように書き込まれるセクターが、 FSCTL_LOCK_VOLUME または FSCTL_DISMOUNT_VOLUMEを使用してボリュームを明示的にロックまたはマウント解除しました。
    • 書き込まれるセクターは、RAW 以外のマウントされたファイル システムを持たないボリューム内に含まれます。
FILE_FLAG_NO_BUFFERINGを使用して CreateFile で開かれたファイルを正常に操作するには、厳密な要件があります。 詳細については、「 ファイル バッファリング」を参照してください。

hFileFILE_FLAG_OVERLAPPED で開かれた場合、次の条件が有効になります。

  • lpOverlapped パラメーターは、有効で一意の OVERLAPPED 構造体を指している必要があります。それ以外の場合、関数は書き込み操作が完了したことを誤って報告する可能性があります。
  • lpNumberOfBytesWritten パラメーターは NULL に設定する必要があります。 書き込まれたバイト数を取得するには、 GetOverlappedResult 関数を使用します。 hFile パラメーターが I/O 入力候補ポートに関連付けられている場合は、GetQueuedCompletionStatus 関数を呼び出して書き込まれたバイト数を取得することもできます。
Windows Server 2012 では、この関数は次のテクノロジでサポートされています。
テクノロジ サポートされています
サーバー メッセージ ブロック (SMB) 3.0 プロトコル はい
SMB 3.0 Transparent Failover (TFO) はい
スケールアウト ファイル共有 (SO) を使う SMB 3.0 はい
クラスターの共有ボリューム ファイル システム (CsvFS) はい
Resilient File System (ReFS) はい
 

同期とファイルの位置

hFileFILE_FLAG_OVERLAPPED で開くと、非同期ファイル ハンドルになります。それ以外の場合は同期です。 OVERLAPPED 構造体を使用する規則は、前に説明したように、それぞれについて若干異なります。
メモ 非同期 I/O 用にファイルまたはデバイスを開いた場合、そのハンドルを使用した WriteFile などの関数に対する後続の呼び出しは、通常は直ちに返されますが、ブロックされた実行に関しては同期的に動作することもできます。 詳細については、「http://support.microsoft.com/kb/156932」を参照してください。
 
非同期ファイル ハンドルの操作に関する考慮事項:
  • 書き込み 操作が完了する前に WriteFile が返される場合があります。 このシナリオでは、 WriteFileFALSE を 返し、 GetLastError 関数は ERROR_IO_PENDINGを返します。これにより、システムが書き込み操作を完了している間も呼び出しプロセスを続行できます。
  • lpOverlapped パラメーターは NULL にすることはできません。また、次の点を考慮して使用する必要があります。
    • OVERLAPPED 構造体で指定されたイベントはシステムによって自動的に設定およびリセットされますが、OVERLAPPED 構造体で指定されたオフセットは自動的には更新されません。
    • WriteFile は、I/O 操作を開始すると、イベントを非署名状態にリセットします。
    • OVERLAPPED 構造体で指定されたイベントは、書き込み操作が完了したときにシグナル状態に設定されます。その時点まで、書き込み操作は保留中と見なされます。
    • 書き込み操作は 、OVERLAPPED 構造体で指定されたオフセットから開始され、システム レベルの書き込み操作が完了する前に WriteFile が返される可能性があるため (書き込み保留中)、オフセットも構造体の他の部分も、イベントが通知されるまでアプリケーションによって変更、解放、または再利用される必要はありません (つまり、書き込みが完了します)。
同期ファイル ハンドルの操作に関する考慮事項:
  • lpOverlappedNULL の場合、書き込み操作は現在のファイル位置から開始され、WriteFile は操作が完了するまで戻らず、WriteFile が返される前にシステムによってファイル ポインターが更新されます。
  • lpOverlappedNULL でない場合、書き込み操作は OVERLAPPED 構造体で指定されたオフセットから開始され、書き込み操作が完了するまで WriteFile は返されません。 システムは、WRITEFile が返される前に、OVERLAPPED Internal フィールドと InternalHigh フィールドとファイル ポインターを更新します。
詳細については、「 CreateFile 」および「 同期および非同期 I/O」を参照してください。

パイプ

匿名パイプが使用されていて、読み取りハンドルが閉じられている場合、WriteFile がパイプの対応する書き込みハンドルを使用して書き込みを試みると、関数は FALSE を返し、GetLastError はERROR_BROKEN_PIPEを返します。

アプリケーションが WriteFile 関数を使用してパイプに書き込むときにパイプ バッファーがいっぱいになった場合、書き込み操作がすぐに完了しない可能性があります。 書き込み操作は、読み取り操作 ( ReadFile 関数を使用) によってパイプに使用できるシステム バッファー領域が増えたときに完了します。

バッファー領域が不足している非ブロッキングバイト モードのパイプ ハンドルに書き込む場合、WriteFile は *lpNumberOfBytesWritten<nNumberOfBytesToWriteTRUE を返します。

パイプの詳細については、「 パイプ」を参照してください。

Transacted Operations

ファイル ハンドルにバインドされたトランザクションがある場合、ファイルの書き込みはトランザクション処理対象です。 詳細については、「 トランザクション NTFS について」を参照してください。

いくつかの例については、「 一時ファイルの作成と使用」および読み取りまたは書き込み用にファイルを開く」を参照してください。

次の C++ の例は、バッファーされていないファイル書き込みのセクターを配置する方法を示しています。 Size 変数は、ファイルに書き込む元のデータ ブロックのサイズです。 バッファーされていないファイル I/O に関するその他の規則については、「 ファイル バッファリング」を参照してください。
#include <windows.h>

#define ROUND_UP_SIZE(Value,Pow2) ((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) & (~(((LONG)(Pow2)) - 1))))

#define ROUND_UP_PTR(Ptr,Pow2)  ((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) & (~(((LONG_PTR)(Pow2)) - 1))))

int main()
{
   // Sample data
   unsigned long bytesPerSector = 65536; // obtained from the GetFreeDiskSpace function.
   unsigned long size = 15536; // Buffer size of your data to write.
   
   // Ensure you have one more sector than Size would require.
   size_t sizeNeeded = bytesPerSector + ROUND_UP_SIZE(size, bytesPerSector);
   
   // Replace this statement with any allocation routine.
   auto buffer = new uint8_t[SizeNeeded];
   
   // Actual alignment happens here.
   auto bufferAligned = ROUND_UP_PTR(buffer, bytesPerSector);

   // ... Add code using bufferAligned here.
   
   // Replace with corresponding free routine.
   delete buffer;
}

要件

   
サポートされている最小のクライアント Windows XP [デスクトップ アプリ | UWP アプリ]
サポートされている最小のサーバー Windows Server 2003 [デスクトップ アプリのみ | UWP アプリ]
対象プラットフォーム Windows
ヘッダー fileapi.h (Windows.h を含む)
Library Kernel32.lib
[DLL] Kernel32.dll

関連項目

CancelIo

CancelIoEx

CancelSynchronousIo

CreateFile

CreateFileTransacted

File Management 関数

GetLastError

GetOverlappedResult

GetQueuedCompletionStatus

ReadFile

SetEndOfFile

WriteFileEx