C++中如何通过std::fstream正确读写二进制SHA1摘要
二进制哈希值读写的正确实现方式
你之前的读写逻辑失效的核心原因是误用了文本流的格式化操作符处理二进制数据,同时没有使用二进制模式打开文件,两个问题共同导致了截断、读不全的情况:
<<操作符输出char*类型时,会默认将其作为C风格字符串处理,遇到值为0x00的字节就会停止写入,根本无法写全包含0值的二进制哈希>>操作符读取字符串时,默认会跳过前导空白字符,且遇到\0、\n、\r、空格等任意控制/空白字符就终止读取,而SHA1原始二进制值中完全可能出现这些字节值,必然出现截断- 未以二进制模式打开文件时,Windows平台会自动对换行符做
\n->\r\n的转义,直接篡改二进制哈希的原始值
正确写入实现
写入二进制数据必须使用文件流的write()成员函数,明确指定写入的字节长度,打开文件时必须追加std::ios::binary标志:
#include <fstream> #include <cstdint> // 例:SHA1固定为20字节原始二进制(对应40位十六进制字符串) uint8_t sha1_binary[20] = {0xC3, 0x0A /* 剩余18个哈希字节按实际值填充 */}; std::ofstream out_file("sha1_store.bin", std::ios::binary); if (!out_file.is_open()) { // 自行处理文件打开失败逻辑,比如权限不足、路径不存在 } // 强制转换为char*类型传入,明确写入20字节 out_file.write(reinterpret_cast<char*>(sha1_binary), sizeof(sha1_binary)); out_file.close();
正确读取实现
读取二进制数据必须使用文件流的read()成员函数,提前分配好固定长度的存储空间,读取后通过gcount()校验实际读取的字节数,避免文件损坏导致的无效数据:
#include <fstream> #include <cstdint> #include <string> std::ifstream in_file("sha1_store.bin", std::ios::binary); if (!in_file.is_open()) { // 自行处理文件打开失败逻辑 } // 方式1:读到固定长度的字节数组中 uint8_t sha1_res[20]; in_file.read(reinterpret_cast<char*>(sha1_res), sizeof(sha1_res)); // 校验实际读取长度,不等于20说明文件损坏或长度不对 if (in_file.gcount() != 20) { // 处理读取失败、哈希不完整的逻辑 } // 方式2:如果要存到std::string中,提前resize到固定长度再读 std::string sha1_str; sha1_str.resize(20); in_file.read(sha1_str.data(), 20); in_file.close();
注意事项
- 只要是读写非文本的原始二进制数据,打开文件时必须加
std::ios::binary,不要依赖系统默认的文本模式 - 二进制读写不要使用
<</>>格式化操作符,这两个接口是为可读文本设计的,对特殊字节值有隐式处理逻辑 - 哈希值是固定长度的(SHA1为20字节、SHA256为32字节),读写时直接按固定长度操作即可,不需要额外加终止符、分隔符
内容的提问来源于stack exchange,提问作者lorem1213
相关产品推荐
相关产品推荐

