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可以使用通訊端或accept函式所傳回的FILE_FLAG_OVERLAPPED旗標或通訊端控制碼,使用CreateFile函式開啟的任何控制碼。

[in] lpBuffer

緩衝區的指標,其中包含要寫入檔案或裝置的資料。

此緩衝區在寫入作業期間必須維持有效狀態。 呼叫端在寫入作業完成之前,不得使用此緩衝區。

[in] nNumberOfBytesToWrite

要寫入檔案或裝置的位元組數目。

值為零會指定 Null 寫入作業。 Null 寫入作業的行為取決於基礎檔案系統或通訊技術。

Windows Server 2003 和 Windows XP: 網路上的管道寫入作業會限制每個寫入的大小。 每個平臺的數量各有不同。 針對 x86 平臺,它是 63.97 MB。 針對 x64 平臺,它是 31.97 MB。 針對 Itanium,其為 63.95 MB。 如需管道的詳細資訊,請參閱一節。

[out, optional] lpNumberOfBytesWritten

使用同步 hFile 參數時,接收寫入位元組數目的變數指標。 WriteFile 會將此值設定為零,再進行任何工作或錯誤檢查。 如果這是非同步作業,以避免發生錯誤的結果,請使用 Null 作為此參數。

只有當lpOverlapped參數不是Null時,此參數才能為Null

Windows 7: 此參數不可為 Null

如需詳細資訊,請參閱<備註>一節。

[in, out, optional] lpOverlapped

如果hFile參數是以FILE_FLAG_OVERLAPPED開啟,則需要重迭結構的指標,否則此參數可以是Null

對於支援位元組位移的 hFile ,如果您使用此參數,您必須指定要開始寫入檔案或裝置的位元組位移。 此位移是藉由設定OVERLAPPED結構的OffsetOffsetHigh成員來指定。 若為不支援位元組位移的 hFile ,則會忽略 OffsetOffsetHigh

若要寫入檔案結尾,請將OVERLAPPED結構的 Offset 和OffsetHigh成員指定為0xFFFFFFFF。 這在功能上相當於先前呼叫CreateFile函式,以使用FILE_APPEND_DATA存取來開啟hFile

For more information about different combinations of lpOverlapped and FILE_FLAG_OVERLAPPED, see the Remarks section and the Synchronization and File Position section.

傳回值

如果函式成功,則傳回值為非零 (TRUE) 。

如果函式失敗或以非同步方式完成,傳回值會是零 (FALSE) 。 若要取得擴充的錯誤資訊,請呼叫 GetLastError 函式。

注意GetLastError程式碼ERROR_IO_PENDING不是失敗;它會指定寫入作業以非同步方式暫止完成。 如需詳細資訊,請參閱<備註>。
 

備註

當發生下列其中一個狀況時, WriteFile 函式會傳回:

  • 要求的位元組數目會寫入。
  • 如果寫入) 遭到封鎖,讀取作業會在管道讀取端釋放緩衝區空間 (。 如需詳細資訊,請參閱 管道一 節。
  • 正在使用非同步控制碼,且寫入是以非同步方式發生。
  • 發生錯誤。
每當有太多未完成的非同步 I/O 要求時, WriteFile 函式可能會因為 ERROR_INVALID_USER_BUFFERERROR_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。

系統會將零個位元組解譯為寫入,以指定 Null 寫入作業, 而 WriteFile 不會截斷或擴充檔案。 若要截斷或擴充檔案,請使用 SetEndOfFile 函式。

字元可以使用 WriteFile 搭配主控台輸出的控制碼,寫入螢幕緩衝區。 函式的確切行為取決於主控台模式。 資料會寫入目前的資料指標位置。 資料指標位置會在寫入作業之後更新。 如需主控台控制碼的詳細資訊,請參閱 CreateFile

寫入通訊裝置時, WriteFile 的行為取決於目前的通訊逾時,使用 SetCommTimeoutsGetCommTimeouts 函式來設定和擷取。 如果您無法設定逾時值,可能會發生無法預測的結果。 如需通訊逾時的詳細資訊,請參閱 COMMTIMEOUTS

雖然單磁區寫入不可部分完成,但除非您使用交易 (,否則多磁區寫入不保證是不可部分完成的,所建立的控制碼是交易控制碼;例如,使用 CreateFileTransacted 建立的控制碼) 。 快取的多磁區寫入不一定會立即寫入磁片;因此,在CreateFile中指定FILE_FLAG_WRITE_THROUGH,以確保整個多磁區寫入磁片,而不會有潛在的快取延遲。

如果您直接寫入具有掛接檔案系統的磁片區,您必須先取得磁片區的獨佔存取權。 否則,您有造成資料損毀或系統不穩定的風險,因為應用程式的寫入可能會與其他來自檔案系統的變更衝突,並將磁片區的內容保持不一致的狀態。 若要避免這些問題,Windows Vista 和更新版本中已進行下列變更:

  • 如果磁片區沒有掛接的檔案系統,或下列其中一個條件成立,磁片區控制碼上的寫入將會成功:
    • 要寫入的磁區是開機磁區。
    • 要寫入的磁區位於檔案系統空間之外。
    • 您已使用 FSCTL_LOCK_VOLUMEFSCTL_DISMOUNT_VOLUME明確鎖定或卸載磁片區。
    • 磁片區沒有實際的檔案系統。 (換句話說,它已掛接 RAW 檔案系統。)
  • 如果下列其中一個條件成立,磁片控制碼上的寫入將會成功:
    • 要寫入的磁區不會落在磁片區的範圍內。
    • 要寫入的磁區落在掛接的磁片區內,但您已使用 FSCTL_LOCK_VOLUMEFSCTL_DISMOUNT_VOLUME明確鎖定或卸載磁片區。
    • 要寫入的磁區落在未掛接檔案系統的磁片區中,而不是 RAW。
使用FILE_FLAG_NO_BUFFERING,成功使用CreateFile開啟的檔案有嚴格的需求。 如需詳細資訊,請參閱 檔案緩衝處理。

如果使用FILE_FLAG_OVERLAPPED開啟hFile,下列條件會生效:

  • lpOverlapped參數必須指向有效且唯一的OVERLAPPED結構,否則函式可能會錯誤地報告寫入作業已完成。
  • lpNumberOfBytesWritten參數應設定為Null。 若要取得寫入的位元組數目,請使用 GetOverlappedResult 函式。 如果 hFile 參數與 I/O 完成埠相關聯,您也可以呼叫 GetQueuedCompletionStatus 函式來取得寫入的位元組數目。
在 Windows Server 2012 中,下列技術支援此函式。
技術 支援
伺服器訊息區 (SMB) 3.0 通訊協定
SMB 3.0 透明容錯移轉 (TFO)
具有向外延展檔案共用的 SMB 3.0 (SO)
叢集共用磁片區檔案系統 (CsvFS)
彈性檔案系統 (ReFS)
 

同步處理和檔案位置

如果 hFile 是以 FILE_FLAG_OVERLAPPED開啟,則為非同步檔案控制代碼;否則為同步。 使用 OVERLAPPED 結構的規則會針對每個結構稍有不同,如先前所述。
注意 如果檔案或裝置已針對非同步 I/O 開啟,則後續使用 該控制碼的 WriteFile 等函式呼叫通常會立即傳回,但也可以同步處理封鎖的執行。 如需詳細資訊,請參閱http://support.microsoft.com/kb/156932
 
使用非同步檔案控制代碼的考慮:
  • WriteFile 可能會在寫入作業完成之前傳回。 在此案例中, WriteFile 會傳回 FALSE ,而 GetLastError 函 式會傳回 ERROR_IO_PENDING,讓呼叫進程在系統完成寫入作業時繼續。
  • lpOverlapped參數不得為Null,而且應該與下列事實搭配使用:
    • 雖然 重迭 結構中指定的事件是由系統自動設定和重設,但是 重迭 結構中指定的位移不會自動更新。
    • 當事件開始 I/O 作業時,WriteFile會將事件重設為非簽署狀態。
    • 重迭結構中指定的事件會在寫入作業完成時設定為訊號狀態;直到該時間為止,寫入作業會被視為擱置中。
    • 由於寫入作業會從 重迭 結構中指定的位移開始,而且 WriteFile 可能會在系統層級寫入作業完成之前傳回, (寫入擱置) ,因此應該先修改、釋放或重複使用應用程式修改、釋放或重複使用結構的任何其他部分,直到事件收到訊號 (, 寫入完成) 。
使用同步檔案控制代碼的考慮:
  • 如果 lpOverlappedNull,則寫入作業會從目前的檔案位置開始, 而且 WriteFile 在作業完成之前不會傳回,而且系統會在 WriteFile 傳回之前更新檔案指標。
  • 如果 lpOverlapped 不是 Null,則寫入作業會從 OVERLAPPED 結構中指定的位移開始, 而且 WriteFile 在寫入作業完成之前不會傳回。 系統會在WriteFile傳回之前更新OVERLAPPED Internal 和 InternalHigh 欄位和檔案指標。
如需詳細資訊,請參閱 CreateFile同步和非同步 I/O

管道

如果使用匿名管道且讀取控制碼已經關閉,當 WriteFile 嘗試使用管道的對應寫入控制碼寫入時,函式會傳回 FALSE ,而 GetLastError傳回ERROR_BROKEN_PIPE

如果當應用程式使用 WriteFile 函式寫入管道時,管道緩衝區已滿,則寫入作業可能不會立即完成。 使用 ReadFile 函式 (讀取作業時,寫入作業將會完成,) 讓管道有更多系統緩衝區空間可用。

寫入至非封鎖的位元組模式管道控制碼時,WriteFile會以 *lpNumberOfBytesWritten<nNumberOfBytesToWrite傳回TRUE

如需管道的詳細資訊,請參閱 管道

交易作業

如果有系結至檔案控制代碼的交易,則會交易檔案寫入。 如需詳細資訊,請參閱 關於交易式 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)
程式庫 Kernel32.lib
DLL Kernel32.dll

另請參閱

CancelIo

CancelIoEx

CancelSynchronousIo

CreateFile

CreateFileTransacted

檔案管理功能

GetLastError

GetOverlappedResult

GetQueuedCompletionStatus

ReadFile

SetEndOfFile

WriteFileEx