关于write和read函数里面的传参类型说明(sizeof和strlen的区分)

发布时间:2026/8/1 9:59:08
关于write和read函数里面的传参类型说明(sizeof和strlen的区分) ostream write( const char* s, streamsize n ); //参数 1const char* 常量字符指针数据源起始地址 //参数 2streamsize 要写入的总字节数量有符号整数类型 istream read( char* s, streamsize n ); //参数 1char* 字符指针存放读取结果的缓冲区 //参数 2streamsize 最多读取的总字节数量为什么传变量 / 结构体要强制转换 (char*)函数只接收 char*任意其他类型int*, 结构体指针都必须强转成 char*把数据当成原始字节流处理。因为标准设计初衷就是用于二进制原始字节读写。read/write的工作逻辑永远不变 只管搬运指定数量的内存字节不解析内容、不转换字符函数本身就是用来读写原始字节的 API。接下来详细讲解怎么区分第二个参数的总字节量关于sizeo和strlen的使用区分看之前先把这两条铁律记住read/write 原始字节搬运函数。只要用这两个函数做数据存档打开文件务必ios::binarystrlen只服务内存中带\0的 C 字符串int、结构体、double 永远沾不上 strlen。示例 1二进制成对读写sizeof 配对标准存档用法适用场景保存 int、结构体、完整字符串之后程序读回来复原#include iostream #include fstream using namespace std; int main() { // 写入 ofstream out(data.bin, ios::binary); int num 12345; char str[] hello; out.write((char*)num, sizeof(num)); // sizeof 写入整数 out.write(str, sizeof(str)); // sizeof写入字符串连带 \0 out.close(); // 读取必须和写入字节数保持一致 ifstream in(data.bin, ios::binary); int read_num; char buf[20]; in.read((char*)read_num, sizeof(read_num)); in.read(buf, sizeof(str)); // 和write的sizeof配对 in.close(); cout read_num endl; cout buf endl; return 0; }对于int类型和结构体类型strlen绝对不能用strlen 只识别以\0结尾的 char 字符串给 int 指针或者结构体直接传进去会发生内存越界、未定义行为。致命后果写入的是 int 内存原始字节记事本打开是一堆乱码符号这根本不是文本存储只要你调用 write 往文件写 int本质就是二进制导出和 “文本存储” 无关。示例 2文本输出write 使用 strlen只存可见字符记事本打开能直接看到文字不保存 \0#include iostream #include fstream #include cstring using namespace std; int main() { ofstream out(test.txt); char str[] hello world; // strlen只写入有效字符丢弃末尾\0 out.write(str, strlen(str)); out.close(); // 重点读取不能用strlen ifstream in(test.txt); char buf[100] {0}; // 方案简单处理一次性读完不知道长度一般循环读取 in.read(buf, sizeof(buf)-1); buf[strlen(buf)] \0; // 手动补上结束符 cout buf endl; return 0; }这段代码是特殊折中写法使用write/read处理人可读文本不属于规范二进制存档写法存在缺陷只适合理解原理工程不推荐。in.read (buf, sizeof (buf)-1) 给手动添加字符串结束符 \0 预留1 个字节的位置。因为write写入时用的strlen导致文件里没有写入\0这个字符而read 只会搬运文件字节不会自动写入 \0。如果读满 100 个字节整个 buf 全部被文件数据占满没有空余位置存放 \0。后续直接当作字符串 cout 打印缺少终止符内存越界出现乱码。这只是文本字符串场景的习惯写法用途把读取到的字节当成 C 风格字符串使用注意二进制读取结构体、int 数组绝对不要写 -1二进制数据不需要\0-1 会少读一个字节数据直接损坏。所以一般二进制读写字符串都用sizeof就行了这样也不需要在读的时候.read (buf, sizeof (buf)-1)错误示范千万不要写char buf[100]; ifstream in(test.txt); // 严重错误read执行前buf是乱码strlen直接越界 in.read(buf, strlen(buf));示例 3工程常用方案字符串先存长度完美解决文本 / 二进制读取难题规避 strlen /sizeof 各种坑#include iostream #include fstream #include cstring using namespace std; int main() { ofstream out(str.bin, ios::binary); char str[] good morning; int len strlen(str); out.write((char*)len, sizeof(len)); // 先写入字符串长度 out.write(str, len); out.close(); // 读取 ifstream in(str.bin, ios::binary); int read_len; in.read((char*)read_len, sizeof(read_len)); // 先读出长度 char buf[100] {0}; in.read(buf, read_len); // 使用读到的长度作为参数 buf[read_len] \0; cout buf endl; return 0; }最后总结1、为什么二进制存储场景写的时候优先 sizeof二进制读写目标把内存里的数据原样存入文件之后读取能完整复原内存数据sizeof 获取变量 / 数组在内存占用全部字节。 如果是字符串数组会连同内存末尾的\0一并写入文件。后续读取拿到全部字节内存结构和写入前完全一致可以直接当成字符串正常使用。strlen 只统计可见字符丢弃\0。 一旦不保存\0文件内没有字符串边界标记等你读取到内存后程序不知道字符串在哪里终止访问字符串会发生内存越界。所以适用于读写int结构体类型的文件所以二进制持久化统一使用 sizeof保证内存镜像完整保存。为什么 read 永远不能拿 strlen 当作第二个参数先记住底层事实strlen 是操作【内存】的函数它扫描一块内存遇到内存中的\0才停止计数。read 是读取【硬盘文件】的函数调用 read 之前数据还不在内存缓冲区。逻辑链条调用 read(buf, strlen(buf)) 时buf 缓冲区此时还没有从文件读到任何数据内存里是随机垃圾值strlen 直接扫描充满乱码的空缓冲区大概率找不到\0疯狂越界访问内存直接触发未定义行为崩溃文件本身只是一堆连续字节。就算文件里原本是文字硬盘文件中不存在自动的\0标记。strlen 根本没有办法提前预知文件里有多少字符。简单一句话你还没把数据读进内存strlen 没有数据可以统计长度它根本无法预判文件内容。最容易踩的坑就是不要在文本文件写入字符串的时候参数使用sizeof弊端①文本编辑器打开会出现乱码\0是 ASCII 空字符。记事本、VS Code 打开 txt遇到0x00字节会显示方框 / 异常乱码。文本文件设计初衷就是给人阅读乱码等于破坏用途。弊端②文本模式下换行转换的隐藏风险重点如果你不加 ios::binary以默认文本模式打开文件Windows 系统会自动转换换行 \n \r\n。一旦发生字节增减你写入的总字节数 和 读出的总字节数不再相等举个最坏情况你写入 sizeof 一共 6 字节hello\0中途换行被系统多插入一个\r最终读取 6 字节时最后读到的不再是\0字符串直接报废。只有带上ios::binary才不会篡改字节但开了ios::binary本质已经脱离标准「文本文件」的规范。清晰划分两套规范写法彻底分清避免混淆方案 A标准文本文件目标人可以用记事本正常打开阅读写入write(str, strlen(str)) 【不存\0】读取read(buf, sizeof(buf)-1)读完手动添加\0方案 B二进制数据存档 目标只给程序读写人不用编辑器打开打开文件带上 ios::binary写入write(str, sizeof(str)) 【存入\0】读取read(buf, sizeof(str))无需-1有\0都是对于字符串而言而int类型不推荐使用对于int或者其他类型double文本文件写读直接用 流插入运算符写 流提取运算符读而对于结构体只能写入二进制文件中就是能是结构体只能配合 read /write 做二进制存储不存在文本存储方案 想要记事本看懂结构体数据不能直接 write必须手动把每个成员转成文本用 逐个输出成员。这篇文章整体看下来其实是写的非常的乱想不利于理解只能作为各位读者在方便的时候看一看记忆的详细的解释大家还是要具体自己去理解能力有限非常抱歉