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結構的Offset和OffsetHigh成員來指定。 若為不支援位元組位移的 hFile ,則會忽略 Offset 和 OffsetHigh 。
若要寫入檔案結尾,請將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 函式。
備註
當發生下列其中一個狀況時, WriteFile 函式會傳回:
- 要求的位元組數目會寫入。
- 如果寫入) 遭到封鎖,讀取作業會在管道讀取端釋放緩衝區空間 (。 如需詳細資訊,請參閱 管道一 節。
- 正在使用非同步控制碼,且寫入是以非同步方式發生。
- 發生錯誤。
若要取消所有擱置的非同步 I/O 作業,請使用:
- CancelIo — 此函式只會取消所指定檔案控制碼的呼叫執行緒所發出的作業。
- CancelIoEx— 此函式會取消執行緒針對指定的檔案控制代碼發出的所有作業。
取消的 I/O 作業已完成,錯誤 ERROR_OPERATION_ABORTED。
WriteFile函式可能會因為ERROR_NOT_ENOUGH_QUOTA而失敗,這表示呼叫程式的緩衝區無法鎖定頁面。 如需詳細資訊,請參閱 SetProcessWorkingSetSize。
如果檔案的一部分被另一個進程鎖定,而寫入作業與鎖定的部分重迭, WriteFile 就會失敗。
寫入檔案時,上次寫入時間不會完全更新,直到所有用於寫入的控制碼都已關閉為止。 因此,若要確保上次寫入時間正確,請在寫入檔案之後立即關閉檔案控制碼。
當寫入作業使用緩衝區時存取輸出緩衝區,可能會導致從該緩衝區寫入的資料損毀。 應用程式不得寫入、重新配置或釋放寫入作業所使用的輸出緩衝區,直到寫入作業完成為止。 使用非同步檔案控制碼時,這特別有問題。 稍後可以在同步 處理和檔案位置 一節和 同步和非同步 I/O中找到同步與非同步檔案控制代碼的其他資訊。
請注意,遠端檔案可能無法正確更新時間戳記。 若要確保結果一致,請使用未緩衝的 I/O。
系統會將零個位元組解譯為寫入,以指定 Null 寫入作業, 而 WriteFile 不會截斷或擴充檔案。 若要截斷或擴充檔案,請使用 SetEndOfFile 函式。
字元可以使用 WriteFile 搭配主控台輸出的控制碼,寫入螢幕緩衝區。 函式的確切行為取決於主控台模式。 資料會寫入目前的資料指標位置。 資料指標位置會在寫入作業之後更新。 如需主控台控制碼的詳細資訊,請參閱 CreateFile。
寫入通訊裝置時, WriteFile 的行為取決於目前的通訊逾時,使用 SetCommTimeouts 和 GetCommTimeouts 函式來設定和擷取。 如果您無法設定逾時值,可能會發生無法預測的結果。 如需通訊逾時的詳細資訊,請參閱 COMMTIMEOUTS。
雖然單磁區寫入不可部分完成,但除非您使用交易 (,否則多磁區寫入不保證是不可部分完成的,所建立的控制碼是交易控制碼;例如,使用 CreateFileTransacted 建立的控制碼) 。 快取的多磁區寫入不一定會立即寫入磁片;因此,在CreateFile中指定FILE_FLAG_WRITE_THROUGH,以確保整個多磁區寫入磁片,而不會有潛在的快取延遲。
如果您直接寫入具有掛接檔案系統的磁片區,您必須先取得磁片區的獨佔存取權。 否則,您有造成資料損毀或系統不穩定的風險,因為應用程式的寫入可能會與其他來自檔案系統的變更衝突,並將磁片區的內容保持不一致的狀態。 若要避免這些問題,Windows Vista 和更新版本中已進行下列變更:
- 如果磁片區沒有掛接的檔案系統,或下列其中一個條件成立,磁片區控制碼上的寫入將會成功:
- 要寫入的磁區是開機磁區。
- 要寫入的磁區位於檔案系統空間之外。
- 您已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME明確鎖定或卸載磁片區。
- 磁片區沒有實際的檔案系統。 (換句話說,它已掛接 RAW 檔案系統。)
- 如果下列其中一個條件成立,磁片控制碼上的寫入將會成功:
- 要寫入的磁區不會落在磁片區的範圍內。
- 要寫入的磁區落在掛接的磁片區內,但您已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME明確鎖定或卸載磁片區。
- 要寫入的磁區落在未掛接檔案系統的磁片區中,而不是 RAW。
如果使用FILE_FLAG_OVERLAPPED開啟hFile,下列條件會生效:
- lpOverlapped參數必須指向有效且唯一的OVERLAPPED結構,否則函式可能會錯誤地報告寫入作業已完成。
- lpNumberOfBytesWritten參數應設定為Null。 若要取得寫入的位元組數目,請使用 GetOverlappedResult 函式。 如果 hFile 參數與 I/O 完成埠相關聯,您也可以呼叫 GetQueuedCompletionStatus 函式來取得寫入的位元組數目。
技術 | 支援 |
---|---|
伺服器訊息區 (SMB) 3.0 通訊協定 | 是 |
SMB 3.0 透明容錯移轉 (TFO) | 是 |
具有向外延展檔案共用的 SMB 3.0 (SO) | 是 |
叢集共用磁片區檔案系統 (CsvFS) | 是 |
彈性檔案系統 (ReFS) | 是 |
同步處理和檔案位置
如果 hFile 是以 FILE_FLAG_OVERLAPPED開啟,則為非同步檔案控制代碼;否則為同步。 使用 OVERLAPPED 結構的規則會針對每個結構稍有不同,如先前所述。- WriteFile 可能會在寫入作業完成之前傳回。 在此案例中, WriteFile 會傳回 FALSE ,而 GetLastError 函 式會傳回 ERROR_IO_PENDING,讓呼叫進程在系統完成寫入作業時繼續。
- lpOverlapped參數不得為Null,而且應該與下列事實搭配使用:
- 如果 lpOverlapped 為 Null,則寫入作業會從目前的檔案位置開始, 而且 WriteFile 在作業完成之前不會傳回,而且系統會在 WriteFile 傳回之前更新檔案指標。
- 如果 lpOverlapped 不是 Null,則寫入作業會從 OVERLAPPED 結構中指定的位移開始, 而且 WriteFile 在寫入作業完成之前不會傳回。 系統會在WriteFile傳回之前更新OVERLAPPED Internal 和 InternalHigh 欄位和檔案指標。
管道
如果使用匿名管道且讀取控制碼已經關閉,當 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 |