图像文件的C++ ifstream

C++ ifstream of image file

我无法将图像文件读入缓冲区。当我读取普通的 ascii 文件时,一切都很好,但当涉及到图像文件时,我怀疑图像文件中有一个 \0 字符?

我需要接收图像文件,将其解析为 16KB 的块进行哈希处理,但是当我这样做时

 std::ifstream ifs;
 ifs.open(file_name, std::ifstream::binary | std::ifstream::in);
 .     
 .
 .
 std::string block;
 char buffer[BLOCK_SIZE];
 .
 .
 .
 memset(buffer, 0, BLOCK_SIZE);
 ifs.read(buffer, BLOCK_SIZE);
 block = buffer;

 std::cout << i << " | block size: " << block.length() 
           << " | buffer size: " << strlen(buffer) << std::endl;

 hash = sha256(block); // string type required for openssl's function

我明白了

0 | block size: 4 | buffer size: 4
1 | block size: 16 | buffer size: 16
2 | block size: 88 | buffer size: 88
3 | block size: 57 | buffer size: 57
4 | block size: 109 | buffer size: 109
5 | block size: 26 | buffer size: 26
6 | block size: 65 | buffer size: 65

如何解决这个问题?我怀疑,例如

junkjunkjunk[=12=]junkjunkjunk

图片文件有随机\0

不能使用strlen()获取二进制数据的长度,因为它是用来获取以null结尾的C风格字符串的长度。使用 = 运算符将二进制数据分配给 std::string 也是一个坏主意。

您可以使用函数 std::istream::gcount() 获取上次 read() 或其他未格式化输入操作读取的长度。

#include <iostream>
#include <fstream>
#include <cstring>

int main(){
    const int BLOCK_SIZE = 16 * 1024;
    const char* file_name = "test.dat";
    int i = 0;
    std::ifstream ifs;
    ifs.open(file_name, std::ifstream::binary | std::ifstream::in);

    char buffer[BLOCK_SIZE];

    memset(buffer, 0, BLOCK_SIZE);
    ifs.read(buffer, BLOCK_SIZE);

    std::cout << i << " | buffer size: " << ifs.gcount() << std::endl;

    return 0;
}

如果 blockstd::string 尝试像这样使用返回的长度:

std::string block;
char buffer[BLOCK_SIZE];

ifs.read(buffer, BLOCK_SIZE);

// check for errors here

block.assign(buffer, ifs.gcount());

函数ifs.gcount() returns读取的字符数。

使用block = buffer强制字符串通过查找空字符来检测数据的结尾。这适用于空终止的 c 风格字符串,但不适用于一般的字符串(或数据)。