[實戰] Windows 文件讀寫函數 `ReadFile()` 和 `WriteFile()` 的阻塞與非阻塞操作詳解(含完整C語言示例)

Windows 文件讀寫函數 ReadFile()WriteFile() 的阻塞與非阻塞操作詳解(含完整C語言示例)

在 Windows 平臺進行文件或設備(如串口、管道)編程時,ReadFile()WriteFile() 是最常用的兩個 API 函數。它們既可以以阻塞方式運行,也可以通過設置標志實現非阻塞方式運行。本文將詳細講解這兩種模式的區別,并提供完整的 C 語言示例代碼。


一、概述:ReadFile()WriteFile() 簡介

這兩個函數定義在 windows.h 頭文件中:

BOOL ReadFile(HANDLE       hFile,LPVOID       lpBuffer,DWORD        nNumberOfBytesToRead,LPDWORD      lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped
);BOOL WriteFile(HANDLE       hFile,LPCVOID      lpBuffer,DWORD        nNumberOfBytesToWrite,LPDWORD      lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped
);
  • hFile:文件或設備的句柄。
  • lpBuffer:數據緩沖區地址。
  • nNumberOfBytesTo(Read/Write):要讀寫的字節數。
  • lpNumberOfBytes(Read/Written):實際讀寫的數據長度。
  • lpOverlapped:重疊結構指針。為 NULL 表示同步(阻塞)操作;否則表示異步(非阻塞)操作。

二、阻塞操作 vs 非阻塞操作

特性阻塞操作(默認)非阻塞操作(異步)
是否等待完成是,調用線程會被掛起直到操作完成否,函數立即返回,操作由系統后臺完成
是否需要 OVERLAPPED 結構
是否支持事件通知可結合事件對象進行通知
是否支持 I/O 完成端口
CPU 使用率較低(等待期間休眠)較高(需主動輪詢或使用回調)
實現復雜度簡單復雜

三、阻塞方式示例

? 示例1:阻塞方式讀寫文件

#include <windows.h>
#include <stdio.h>int main() {HANDLE hFile = CreateFile(TEXT("testfile.txt"),GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if (hFile == INVALID_HANDLE_VALUE) {printf("CreateFile failed (%d)\n", GetLastError());return 1;}const char* buffer = "Hello, World!";DWORD bytesWritten;// 寫入文件(阻塞)if (!WriteFile(hFile, buffer, strlen(buffer), &bytesWritten, NULL)) {printf("WriteFile failed (%d)\n", GetLastError());CloseHandle(hFile);return 1;}printf("Wrote %d bytes\n", bytesWritten);// 移動文件指針到開頭SetFilePointer(hFile, 0, NULL, FILE_BEGIN);char readBuffer[256];DWORD bytesRead;// 讀取文件(阻塞)if (!ReadFile(hFile, readBuffer, sizeof(readBuffer), &bytesRead, NULL)) {printf("ReadFile failed (%d)\n", GetLastError());CloseHandle(hFile);return 1;}readBuffer[bytesRead] = '\0';  // 添加字符串結束符printf("Read: %s\n", readBuffer);CloseHandle(hFile);return 0;
}

📌 編譯命令(MinGW / GCC):

gcc -o blocking_example blocking_example.c -mwindows

四、非阻塞方式示例(異步操作)

使用 OVERLAPPED 結構和事件對象可以實現非阻塞讀寫。下面是一個完整的異步讀取示例:

? 示例2:非阻塞方式讀取文件(異步 + 事件通知)

#include <windows.h>
#include <stdio.h>int main() {HANDLE hFile = CreateFile(TEXT("testfile.txt"),GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,  // 設置為異步操作NULL);if (hFile == INVALID_HANDLE_VALUE) {printf("CreateFile failed (%d)\n", GetLastError());return 1;}char buffer[256];DWORD bytesRead;OVERLAPPED overlapped = {0};overlapped.Offset = 0;overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  // 創建事件// 異步讀取BOOL result = ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, &overlapped);if (!result && GetLastError() != ERROR_IO_PENDING) {printf("ReadFile error (%d)\n", GetLastError());CloseHandle(hFile);return 1;}printf("Waiting for asynchronous read to complete...\n");// 等待事件觸發(可替換為 WaitForMultipleObjects 或其他機制)WaitForSingleObject(overlapped.hEvent, INFINITE);// 獲取最終結果if (!GetOverlappedResult(hFile, &overlapped, &bytesRead, FALSE)) {printf("GetOverlappedResult failed (%d)\n", GetLastError());} else {buffer[bytesRead] = '\0';printf("Async read completed: %s\n", buffer);}CloseHandle(overlapped.hEvent);CloseHandle(hFile);return 0;
}

📌 編譯命令:

gcc -o async_read async_read.c -mwindows

五、總結對比

功能阻塞方式非阻塞方式(異步)
是否立即返回
是否適合大量并發
是否支持事件通知
是否需要處理線程阻塞不需要需要配合事件、線程池或 I/O 完成端口
適用場景簡單文件讀寫、調試高性能網絡服務、串口通信、異步I/O

六、擴展建議

  • 對于高性能服務器程序,建議結合 I/O 完成端口(IOCP) 使用異步模型。
  • 如果需要同時處理多個異步請求,應使用 線程池WaitForMultipleObjects
  • 對于串口、管道等設備通信,通常推薦使用異步模式提升響應能力。

七、結語

Windows 提供了靈活的文件和設備讀寫接口,開發者可以根據需求選擇阻塞模式非阻塞異步模式。理解兩者的區別及使用方法,是編寫高效 Windows 應用的關鍵一步。希望本篇博客能幫助你更好地掌握 ReadFile()WriteFile() 的使用技巧!


研究學習不易,點贊易。
工作生活不易,收藏易,點收藏不迷茫 :)


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87683.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87683.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87683.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Singularity 安裝

Singularity 是什么? 核心功能:用于創建/運行容器(將應用+依賴打包的獨立環境)。 與 Docker 的區別:專為 HPC(高性能計算)設計,無需后臺守護進程,支持非 root 運行容器(但安裝本身需 root 權限)。 適用于在具有 root 權限的計算機上從源代碼安裝 Singularity。…

辯證視角下 “辮子戲” 的文化反思與價值重構

前陣子播出的《人生若如初見》刻意美化晚清封建統治階級&#xff0c;淡化甚至掩蓋清政府閉關鎖國、喪權辱國、殘酷壓迫民眾等歷史真相&#xff0c;將本應批判反思的腐朽統治包裝成值得歌頌的對象&#xff1b;在歷史敘事上&#xff0c;或通過虛構、篡改重要歷史事件和人物形象&a…

MCP-server

&#x1f4a1; 說明&#xff1a;該模塊是 MCP 服務器的 數據中繼層&#xff0c;確保安全高效地從分布式來源獲取模型及其上下文&#xff0c;適用于邊緣計算和聯邦學習場景。若要查看完整代碼&#xff0c;建議直接訪問 GitHub 鏈接

第3講、LangChain性能優化:上下文緩存與流式響應實戰指南

目錄 概述上下文緩存優化流式響應優化復雜對話場景性能優化用戶體驗優化策略完整實現示例性能監控與調優總結 概述 在復雜對話場景中&#xff0c;大型語言模型面臨著響應延遲、重復計算、上下文管理等挑戰。本文將詳細介紹如何通過LangChain的上下文緩存和流式響應功能來優化…

http中GET和POST、PUT之間的區別

在HTTP協議中&#xff0c;GET、POST和PUT是三種最常用的請求方法&#xff0c;它們的主要區別如下&#xff1a; 1. GET 用途&#xff1a;用于請求資源&#xff08;查詢數據&#xff09;&#xff0c;不應修改服務器狀態。 參數傳遞&#xff1a;通過URL的查詢字符串&#xff08;…

埃夫特各種系列機器人運動學建模、軌跡規劃和工作空間求解

要求&#xff1a; 1.理論分析 1.1 正向運動學&#xff1a;根據D-H法完成機器人的正向運動學&#xff08;數學建模后基于Matlab計算公式&#xff09;&#xff1b; 1.2 工作空間分析&#xff1a;根據正向運動學結果&#xff0c;運用 MATLAB進行工作空間分析&#xff0c;完成工…

VUE3 路由的跳轉方法

Routerlink跳轉方法 name屬性對應了路由文件配置的name path屬性對應了路由的路徑 <RouterLink to"/login">點擊跳轉登陸</RouterLink> <RouterLink :to"{name:login}">點擊跳轉登陸</RouterLink> <RouterLink :to"{pat…

數據庫中間件ShardingSphere5

一、高性能架構模式 數據庫集群&#xff0c;第一種方式“讀寫分離”&#xff0c;第二種方式“數據庫分片”。 1.1 讀寫分離架構 讀寫分離原理&#xff1a;將數據庫讀寫操作分散到不同的節點上。 讀寫分離的基本實現&#xff1a; 主庫負責處理事務性的增刪改操作&#xff0c…

C++11 右值引用(Rvalue Reference)

在 C++11 中,右值引用(Rvalue Reference) 是一個革命性的語言特性,它為現代 C++ 的性能優化、資源管理以及語義清晰化奠定了基礎。通過引入 T&& 語法,C++11 支持了 移動語義(Move Semantics) 和 完美轉發(Perfect Forwarding),極大地提升了程序效率和代碼表達…

skynet源碼學習-skynet_main入口

skynet源碼學習-skynet_main入口 核心功能與啟動流程Shell腳本啟動示例main函數參數處理其他相關聯函數解析1. 配置加載器解析2. 環境變量設置3. 配置解析函數 核心配置項解析典型配置文件分析服務啟動與運行核心服務啟動流程完整啟動時序圖 核心功能與啟動流程 Skynet 的啟動…

前端圖文混排頁面一鍵導出PDF最佳實踐 —— 以Vue3+html2pdf.js為例

前言 在現代管理系統中,數據的歸檔、分享和線下流轉需求日益增長。如何將前端頁面的圖文內容高質量導出為PDF,成為許多企業和開發者關注的技術點。本文以實際項目為例,系統梳理前端導出PDF的完整實現思路與優化經驗。 一、項目背景與需求分析 1.1 背景故事 在某管理系統的…

19|Whisper+ChatGPT:請AI代你聽播客

今天&#xff0c;我們的課程開始進入一個新的主題了&#xff0c;那就是語音識別。過去幾周我們介紹的ChatGPT雖然很強大&#xff0c;但是只能接受文本的輸入。而在現實生活中&#xff0c;很多時候我們并不方便停下來打字。很多內容比如像播客也沒有文字版&#xff0c;所以這個時…

linux常用設置

1&#xff0c;ubuntu設置ssh-agent進入shell時自動加載 一&#xff0c;添加自動加載腳本&#xff0c;vim /etc/profile.d/keychain.sh # /etc/profile.d/keychain.sh # 自動啟動 ssh-agent 并加載多個私鑰 export KEYCHAIN_HOME"/root/.keychain" # 多個key&#xf…

電子電氣架構 --- 軟件供應商如何進入OEM體系

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 簡單,單純,喜歡獨處,獨來獨往,不易合同頻過著接地氣的生活,除了生存溫飽問題之外,沒有什么過多的欲望,表面看起來很高冷,內心熱情,如果你身…

破解數據可視化難題:帶軸斷裂的柱狀圖繪制全指南

引言&#xff1a;當數據跨度讓圖表失真時&#xff0c;軸斷裂技術如何力挽狂瀾&#xff1f; 在數據可視化的世界里&#xff0c;我們常常會遇到這樣的困境&#xff1a;一組數據中既有 "巨無霸" 般的極端值&#xff0c;又有需要精細展示的小數據。比如在財務報表中&…

以太網基礎①以太網相關通信接口

1. 今日摸魚任務 需要學習使用ZYNQ的以太網傳輸SCPI指令 需要把PL PS兩側的都用起來&#xff08;加油鴨&#xff01;&#xff09; 吶吶吶 今天就先學一下基礎知識唄 02_【邏輯教程】基于HDL的FPGA邏輯設計與驗證教程V3.5.2.pdf 51 以太網相關通信接口詳解 52 以太網&#xff…

FPGA基礎 -- Verilog 共享任務(task)和函數(function)

Verilog 中共享任務&#xff08;task&#xff09;和函數&#xff08;function&#xff09; 的詳細專業培訓&#xff0c;適合具有一定 RTL 編程經驗的工程師深入掌握。 一、任務&#xff08;task&#xff09;與函數&#xff08;function&#xff09;的基本區別 特性taskfunctio…

學習大模型---需要掌握的數學知識

1. 線性代數&#xff1a;樂高積木的世界 想象你有很多樂高積木塊。線性代數就是研究怎么用這些積木塊搭建東西&#xff0c;以及這些搭建好的東西有什么特性的學問。 向量&#xff1a; 就像一個有方向的箭頭&#xff0c;或者一組排好隊的數字。比如&#xff1a; 一個箭頭&…

明遠智睿RK3506開發板:多核異構架構賦能高可靠性工業與商業應用

在工業4.0與物聯網&#xff08;IoT&#xff09;技術快速發展的背景下&#xff0c;嵌入式系統對性能、功耗、可靠性和實時性的要求日益嚴苛。針對這一趨勢&#xff0c;瑞芯微推出的RK3506開發板憑借其創新的三核A7單核M0多核異構架構、高能低耗設計以及豐富的外設資源&#xff0…

【AI時代速通QT】第二節:Qt SDK 的目錄介紹和第一個Qt Creator項目

目錄 一、認識 Qt SDK 的目錄結構 二、第一個 Qt 程序 2.1 Qt Creator 創建項目 2.2 介紹項目各文件 三、揭秘 Qt 的構建過程 四、運行項目與總結 &#x1f3ac; 攻城獅7號&#xff1a;個人主頁 &#x1f525; 個人專欄:CQT跨平臺界面編程 ?? 君子慎獨! &#x1f308…