【C++】ReadFile概述,及实践使用时ReadFile的速率影响研究

ReadFile 函数概述

ReadFile 是 Windows API 函数,用于从文件或设备(如串口、硬盘等)中读取数据。它是同步和异步 I/O 操作的基础函数。


函数原型

BOOL ReadFile(_In_ HANDLE hFile,                          // 文件或设备句柄_Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) LPVOID lpBuffer, // 缓冲区_In_ DWORD nNumberOfBytesToRead,            // 预期读取的字节数_Out_opt_ LPDWORD lpNumberOfBytesRead,      // 实际读取的字节数,会根据_In_ DWORD返回给他_Inout_opt_ LPOVERLAPPED lpOverlapped       // 异步操作参数
);

参数详解

1. HANDLE hFile
  • 含义:表示需要读取数据的目标。
    • 可以是文件句柄(通过 CreateFile 打开)或设备句柄(如串口 COM1)。
    • 例如,读取串口数据时,通过 CreateFile 获得串口句柄。
2. LPVOID lpBuffer
  • 含义:指向缓冲区的指针ReadFile 将读取的数据存储到该缓冲区中。
  • 大小要求:缓冲区大小应至少等于 nNumberOfBytesToRead,以避免越界。
  • 类型LPVOID,可转换为任意指针类型(如 char*)。
3. DWORD nNumberOfBytesToRead
  • 含义:预期读取的字节数,ReadFile 尝试从文件或设备读取该数量的数据。
  • 注意
    • 如果设备中数据不足,ReadFile 可能返回成功,但实际读取的字节数会少于此值(存储在 lpNumberOfBytesRead 中)。
4. LPDWORD lpNumberOfBytesRead
  • 含义:指向 DWORD 类型变量的指针,用于接收实际读取的字节数。
  • 可选性
    • 如果为 nullptr,表示调用方不关心读取了多少字节(不推荐)。
  • 返回值含义
    • 函数执行成功后,该变量存储实际读取的字节数。
5. LPOVERLAPPED lpOverlapped
  • 含义:指向 OVERLAPPED 结构的指针,用于异步操作。
  • 同步与异步
    • nullptr:表示同步操作,ReadFile 会阻塞,直到读取完成或超时。
    • nullptr:表示异步操作,ReadFile 会立即返回,读取操作会在后台完成。

返回值

  • BOOL 类型
    • TRUE:读取成功。
    • FALSE:读取失败,调用 GetLastError 获取错误代码。
  • 常见错误
    • ERROR_HANDLE_EOF:已到达文件末尾(EOF)。
    • ERROR_IO_PENDING:对于异步操作,表示读取请求已提交但尚未完成。

函数用途

ReadFile 广泛用于以下场景:

  1. 文件读取:从文件系统中读取内容。
  2. 串口通信:读取串口(COM)数据,常用于嵌入式设备通信。
  3. 网络通信(通过设备接口):读取基于设备接口的网络数据。
  4. 传感器数据读取:从硬件传感器中读取数据。

示例 1:从文件读取数据

从文件中读取内容并打印到控制台:

#include <windows.h>
#include <iostream>int main() {// 打开文件HANDLE hFile = CreateFile("example.txt",          // 文件路径GENERIC_READ,           // 读取权限0,                      // 共享模式NULL,                   // 安全属性OPEN_EXISTING,          // 打开已存在的文件FILE_ATTRIBUTE_NORMAL,  // 属性NULL                    // 模板文件句柄);if (hFile == INVALID_HANDLE_VALUE) {std::cerr << "无法打开文件,错误代码:" << GetLastError() << std::endl;return 1;}// 读取数据char buffer[128] = {0};  // 数据缓冲区DWORD bytesRead = 0;     // 实际读取的字节数if (ReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {std::cout << "成功读取 " << bytesRead << " 字节:" << std::endl;std::cout << buffer << std::endl;} else {std::cerr << "读取失败,错误代码:" << GetLastError() << std::endl;}// 关闭文件CloseHandle(hFile);return 0;
}

示例 2:串口数据读取

从串口(如 COM2)读取数据:

#include <windows.h>
#include <iostream>int main() {// 打开串口HANDLE hSerial = CreateFile("COM2",                // 串口名称GENERIC_READ,          // 读取权限0,                     // 共享模式NULL,                  // 安全属性OPEN_EXISTING,         // 打开已存在的设备0,                     // 属性NULL                   // 模板文件句柄);if (hSerial == INVALID_HANDLE_VALUE) {std::cerr << "无法打开串口,错误代码:" << GetLastError() << std::endl;return 1;}// 设置串口参数(波特率、数据位等)DCB dcb = {0};//Device Control Blockdcb.DCBlength = sizeof(DCB);GetCommState(hSerial, &dcb);dcb.BaudRate = CBR_9600;dcb.ByteSize = 8;dcb.Parity = NOPARITY;dcb.StopBits = ONESTOPBIT;SetCommState(hSerial, &dcb);// 读取数据char buffer[128] = {0};DWORD bytesRead = 0;if (ReadFile(hSerial, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {std::cout << "成功读取 " << bytesRead << " 字节:" << std::endl;for (DWORD i = 0; i < bytesRead; ++i) {std::cout << "0x" << std::hex << static_cast<int>(buffer[i]) << " ";}std::cout << std::endl;} else {std::cerr << "读取失败,错误代码:" << GetLastError() << std::endl;}// 关闭串口CloseHandle(hSerial);return 0;
}

异步模式的应用

如果需要非阻塞读取,可以使用 OVERLAPPED 结构:

OVERLAPPED overlapped = {0};
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);BOOL result = ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, &overlapped);
if (!result && GetLastError() == ERROR_IO_PENDING) {// 等待异步操作完成WaitForSingleObject(overlapped.hEvent, INFINITE);GetOverlappedResult(hFile, &overlapped, &bytesRead, FALSE);
}

总结

ReadFile 的作用
  • 从文件或设备读取数据,支持同步和异步模式。
典型应用
  • 文件操作:读取文本或二进制文件。
  • 串口通信:读取嵌入式设备数据。
  • 网络设备:读取基于接口的网络数据。
优点
  • 支持异步 I/O,提高程序性能。
  • 适用于广泛的文件和设备操作场景。
注意事项
  • 缓冲区大小要足够大以避免数据截断。
  • 在串口和异步模式中,需额外配置超时和事件处理机制。

补充 1 关于DBC

DCB dcb = {0}; 是一个用于初始化并配置串口通信参数的结构体。在 Windows API 中,DCBDevice Control Block)结构用于描述串口通信的控制设置,例如波特率、数据位、停止位、校验位等。


DCB 结构的定义

typedef struct _DCB {DWORD DCBlength;       // 结构体的大小(字节)DWORD BaudRate;        // 波特率(如 9600、115200)DWORD fBinary: 1;      // 是否使用二进制模式DWORD fParity: 1;      // 是否启用校验位DWORD fOutxCtsFlow: 1; // 是否启用 CTS 流控制DWORD fOutxDsrFlow: 1; // 是否启用 DSR 流控制DWORD fDtrControl: 2;  // DTR 控制流设置DWORD fDsrSensitivity: 1; // DSR 灵敏度DWORD fTXContinueOnXoff: 1; // 接收 XOFF 后是否继续传输DWORD fOutX: 1;        // 是否启用 XON/XOFF 流控制(输出)DWORD fInX: 1;         // 是否启用 XON/XOFF 流控制(输入)DWORD fErrorChar: 1;   // 是否替换错误字符DWORD fNull: 1;        // 是否丢弃 NULL 字节DWORD fRtsControl: 2;  // RTS 控制流设置DWORD fAbortOnError: 1;// 是否在错误时中止读/写操作DWORD fDummy2: 17;     // 保留位WORD wReserved;        // 保留字段WORD XonLim;           // XON 限制WORD XoffLim;          // XOFF 限制BYTE ByteSize;         // 每个字节的数据位数(4-8 位)BYTE Parity;           // 校验类型(无、奇、偶、标记、空)BYTE StopBits;         // 停止位(1、1.5 或 2 位)char XonChar;          // XON 字符char XoffChar;         // XOFF 字符char ErrorChar;        // 替换错误的字符char EofChar;          // 文件结束符char EvtChar;          // 事件字符WORD wReserved1;       // 保留字段
} DCB, *LPDCB;

补充2 影响速度的因素

ReadFile 的读取缓冲区的速度和范围没有固定的值,它受到以下多个因素的影响。具体的读取速度和数据范围会因场景、设备以及系统配置而有所不同。


1. 影响 ReadFile 读取速度的因素

文件读取速度
  • 现代 SSD:几百 MB/s。
  • HDD:50-200 MB/s。
串口读取速度
  • 受波特率限制:
    • 9600 bps:约 960 字节/秒。
    • 115200 bps:约 11,520 字节/秒。
  • 调整缓冲区大小可以提升效率。
影响速度的关键点
  • 硬件速率:文件存储设备、串口波特率等。
  • 用户缓冲区大小:每次读取的最大字节数。
  • 系统缓冲区:通过 SetupComm 设置大小。
  • 数据可用性:设备中数据是否已准备好。

通过合理调整缓冲区大小与 I/O 参数,ReadFile 的速度可以优化到设备允许的上限范围。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/477628.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用EFK收集k8s日志

首先我们使用EFK收集Kubernetes集群中的日志&#xff0c;本次实验讲解的是在Kubernetes集群中启动一个Elasticsearch集群&#xff0c;如果企业内已经有了Elasticsearch集群&#xff0c;可以直接将日志输出至已有的Elasticsearch集群。 文章目录 部署elasticsearch创建Kibana创建…

Qt入门1——认识Qt的几个常用头文件和常用函数

1.头文件 ① #include <QPushButton>——“按钮”头文件&#xff1b; ② #include <QLabel>——“标签”头文件&#xff1b; ③ #include <QFont>——“字体”头文件&#xff1b; ④#include <QDebug>——输出相关信息&#xff1b; 2. 常用函数/类的基…

【Linux驱动开发】irq中断配置API及中断应用 阻塞休眠和非阻塞的驱动操作

【Linux驱动开发】irq中断配置API及中断应用 阻塞休眠和非阻塞的驱动操作 文章目录 中断操作注册和释放中断中断服务函数使能和禁止上半部和下半部软中断tasklet工作队列 设备节点中的中断中断号API函数获取中断号获取中断信息 中断应用读取设备树节点获取中断号获取中断触发方…

Linux设置以及软件的安装(hadoop集群安装02)

一、Linux的常见设置 1、设置静态IP vi /etc/sysconfig/network-scripts/ifcfg-ens33 如何查看自己的虚拟机的网关&#xff1a; 完整的配置&#xff08;不要拷贝我的&#xff09;&#xff1a; TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no&…

excel版数独游戏(已完成)

前段时间一个朋友帮那小孩解数独游戏&#xff0c;让我帮解&#xff0c;我看他用电子表格做&#xff0c;只能显示&#xff0c;不能显示重复&#xff0c;也没有协助解题功能&#xff0c;于是我说帮你做个电子表格版的“解题助手”吧&#xff0c;不能直接解题&#xff0c;但该有的…

网络安全,文明上网(5)注重隐私加密

前言 为了维护个人数据和通信的安全&#xff0c;防止非法获取或泄露&#xff0c;可以采用多种隐私保护技术。 技术要点 1. 个人数据去标识化和匿名化方法&#xff1a; K匿名性(K-Anonymity)&#xff1a;由Sweeney提出&#xff0c;通过对个人数据进行匿名化处理&#xff…

【Unity】 GamePlay开发:通用的检查点/成就/条件触发系统

特别适用于各种解谜关卡, 成就系统&#xff0c;任务系统&#xff0c;的 通用事件处理 CheckPointHandler.cs随便挂在场景中的某个物体上 (单例模式&#xff0c;场景中只要有一个&#xff09; 1) How To Use CheckPoint Events是一个列表&#xff0c;每个元素是一个组合事件&…

P1 练习卷(C++4道题)

1.纷繁世界 内存限制&#xff1a;256MB 时间限制&#xff1a;1s 问题描述 这是一个纷繁复杂的世界。 某一天清晨你起床很迟&#xff0c;没有吃上早饭。于是你骑着自行车去超市&#xff0c;但是你又发现商店的工作人员已经重新贴上了价格标签&#xff0c;零食价格都涨了50%。你…

私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?

在当今数字化、网络化的时代背景下&#xff0c;视频监控技术已广泛应用于各行各业&#xff0c;成为保障安全、提升效率的重要工具。然而&#xff0c;面对复杂多变的监控需求和跨区域、网络化的管理挑战&#xff0c;传统的视频监控解决方案往往显得力不从心。 EasyCVR视频融合云…

物体网格弹性变形---Unity中实现

在游戏引擎场景中的3D物体是由一定数量的点、面组成的&#xff0c;如下图&#xff1a; 要使这些物体变形就是改变3D物体每个顶点状态。 1.首先在Unity场景中增加一个球体&#xff0c;如下图 3D组件默认拥有MeshFilter、meshRenderer、Collider组件&#xff0c;分别用来获取Mes…

Java爬虫:获取商品详情的实践之旅

在当今这个信息爆炸的时代&#xff0c;数据的价值日益凸显。对于电商行业来说&#xff0c;商品详情的获取尤为重要&#xff0c;它不仅关系到产品的销售&#xff0c;还直接影响到用户体验。传统的人工获取方式耗时耗力&#xff0c;而自动化的爬虫技术则提供了一种高效解决方案。…

【LLM】一文学会SPPO

博客昵称&#xff1a;沈小农学编程 作者简介&#xff1a;一名在读硕士&#xff0c;定期更新相关算法面试题&#xff0c;欢迎关注小弟&#xff01; PS&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟沈小农&#xff0c;希望我的文章能帮助到你。欢迎大家在…

腾讯云 AI 代码助手:产品研发过程的思考和方法论

一、文章摘要 本文将详细阐述 腾讯云 AI 代码助手的历史发展形态与产品整体架构&#xff0c;并从技术、研发方法论的角度分别阐述了产品的研发过程。 全文阅读约 5&#xff5e;8 分钟。 二、产品布局 AI 代码助手产品经历了三个时代的发展 第一代诸如 Eclipse、Jetbrains、V…

RabbitMQ实现异步下单与退单

前言&#xff1a; 在电商项目中的支付模块也是一个很重要的模块&#xff0c;其中下订操作以及退订操作就是主要的操作。其次的下单是同步下单&#xff0c;也就是第三方支付、数据库扣减、积分增加、等等其他业务操作&#xff0c;等待全部执行完毕后向用户返回成功响应请求。对…

SQL99版全外连接和交叉连接和总结

全外连接MySQL不支持 elect 查询列表 from 表名1 表别名1 cross join 表名2 表别名2 on 连接条件 ...... ; 交叉连接 就两个记录做笛卡尔积&#xff01;没什么好说的&#xff0c;基本也没用过&#xff01; 总结

从〇开始深度学习(0)——背景知识与环境配置

从〇开始深度学习(0)——背景知识与环境配置 文章目录 从〇开始深度学习(0)——背景知识与环境配置写在前面1.背景知识1.1.Pytorch1.2.Anaconda1.3.Pycharm1.4.CPU与GPU1.5.整体关系 2.环境配置2.1.准备工作2.1.1.判断有无英伟达显卡2.1.2.清理电脑里的旧环境 2.1.安装Anaconda…

PHP屏蔽海外IP的访问页面(源代码实例)

PHP屏蔽海外IP的访问页面&#xff08;源代码实例&#xff09;&#xff0c;页面禁用境外IP地址访问 <?php/*** 屏蔽海外ip访问* 使用ip2long函数得到ip转为整数的值&#xff0c;判断值是否在任一一个区间中* 以下是所有国内ip段* 调用方法&#xff1a;IschinaIp($ALLIPS)* …

“iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题

目录 文件和证书未加载或特殊字符问题 证书过期或Profile文件错误 确认开发者证书和私钥是否匹配 创建证书选择错误问题 申请苹果 AppId时勾选服务不全问题 ​总结 在上线ios平台的时候&#xff0c;在Hbuilder中打包遇见了问题&#xff0c;生成ipa文件时候&#xff0c;一…

VUE 的前置知识

一、JavaScript----导图导出 1. JS 提供的导入导出机制&#xff0c;可以实现按需导入 1.1 在html页面中可以把JS文件通过 <script src"showMessage.js"></script> 全部导入 1.2 通过在JS文件中写export关键字导出通过 <script src"showMessage…

量子卷积神经网络

量子神经网络由量子卷积层、量子池化层和量子全连接层组成 量子卷积层和量子池化层交替放置&#xff0c;分别实现特征提取和特征降维&#xff0c;之后通过量子全连接层进行特征综合 量子卷积层、量子池化层和量子全连接层分别由量子卷积单元、量子池化单元和量子全连接单元组…