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

[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結構的OffsetOffsetHigh成員同時指定為 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 掛接檔案系統的磁片區內。
使用createFile FILE_FLAG_NO_BUFFERING 成功使用 CreateFile開啟的檔案有嚴格的需求。 如需詳細資訊,請參閱 檔案緩衝

如果 hFile 是以 FILE_FLAG_OVERLAPPED開啟,則下列條件會生效:

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

同步處理和檔案位置

如果使用FILE_FLAG_OVERLAPPED開啟hFile,則為非同步檔案控制代碼;否則為同步。 使用 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