如何从含长度标识的内存映射文件中提取unsigned int类型长度值?
嘿,这个问题我遇到过好多次了——内存映射文件里提取前置的长度值,核心得先搞清楚你的数字是二进制存储还是文本形式存储,毕竟你举的例子里是10(换行)abcdefghij,看起来像是文本存的数字,我分两种情况给你拆解清楚:
情况1:二进制形式存储的unsigned int(推荐这种方式)
如果是直接把unsigned int的二进制数据写入内存映射文件(比如用memcpy把变量值写到文件头),那提取起来超简单,完全不用纠结逐字符复制的问题:
因为内存映射的地址是连续的内存块,你可以直接把映射起始地址转成unsigned int*来取值,或者用memcpy更稳妥(避免内存对齐问题):
// 假设pMapView是MapViewOfFile返回的void*指针 // 方法1:直接强制转换(简单但要注意内存对齐) unsigned int dataLength = *(unsigned int*)pMapView; // 方法2:用memcpy(更安全,不在乎对齐) unsigned int dataLength; memcpy(&dataLength, pMapView, sizeof(unsigned int));
拿到长度后,实际数据的起始地址就是(char*)pMapView + sizeof(unsigned int),直接读取对应长度的字节就行。
情况2:文本形式存储的数字(比如你的例子)
如果是像例子里那样,把数字以字符串形式(比如"10\n")存在文件开头,那就要先把文本转成unsigned int:
- 从映射内存的起始位置开始,找到分隔符(换行、空格或你约定的其他符号);
- 把分隔符前的字符序列转换成unsigned int;
- 跳过分隔符后就是实际数据。
给你个代码示例,假设分隔符是换行:
char* pStart = (char*)pMapView; // 找到换行符的位置 char* pDelimiter = strchr(pStart, '\n'); if (pDelimiter == NULL) { // 处理错误:没找到分隔符,格式不对 return; } // 临时把分隔符改成字符串结束符,方便转换 *pDelimiter = '\0'; // 用strtoul转换,比atoi更安全,能处理错误 unsigned int dataLength = strtoul(pStart, NULL, 10); // 恢复原来的分隔符 *pDelimiter = '\n'; // 实际数据的起始地址就是分隔符的下一个位置 char* pActualData = pDelimiter + 1; // 现在就可以读取dataLength长度的字符了
如果你的分隔符不是换行,换成你实际用的就行(比如空格就用strtok或者自己遍历找)。另外记得检查转换是否成功,比如strtoul的第二个参数可以用来判断有没有非数字字符。
额外注意点
- 优先用二进制存储:文本形式需要处理分隔符、数字长度变化,效率也低;二进制直接存固定字节数,读取快还不容易出错。
- 内存对齐问题:如果用强制转换指针的方式取二进制值,要确保映射的内存地址符合unsigned int的对齐要求(比如4字节对齐),不然可能触发CPU的对齐错误,这时候
memcpy是更稳妥的选择。 - 字节序问题:如果是跨平台读写内存映射文件,要注意大端小端的问题(比如用
htonl/ntohl转换),同一平台就不用管。
内容的提问来源于stack exchange,提问作者Navjot Singh
相关产品推荐
相关产品推荐

