想用C++将图像的二进制数据放入RocksDB

Want to put binary data of images into RocksDB in C++

  1. 我正在尝试在键值存储中保存图像的二进制数据
  2. 1、使用“fread”函数读取数据。 2、保存到RocksDB中。 3、从RocksDB中获取数据,并将数据还原为图片形式。
  3. 现在不知道是不是第3步第2步有问题

第二步放

#include <iostream>
#include <string.h> 
#include "rocksdb/db.h"

DB* db;
Options options;
options.create_if_missing = true;


Status s = DB::Open(options, <DBPath>, &db);
assert(s.ok());

//read image
FILE* file_in;
int fopen_err = fopen_s(&file_in, <input_file_path>, "rb");
if (fopen_err != 0) {
    printf(input_file_path, "%s is not valid");;
}

fseek(file_in, 0, SEEK_END);
long int file_size = ftell(file_in);
rewind(file_in);

//malloc buffer
char* buffer = (char*)malloc(file_size);
if (buffer == NULL) { printf("Memory Error!!"); }
fread(buffer, file_size, 1, file_in);

//main func
db->Put(WriteOptions(), file_key, buffer);
assert(s.ok());

fclose(file_in);
free(buffer);
buffer = NULL;
delete db;  

第三步获取

#include <iostream>
#include <string.h> 
#include "rocksdb/db.h"

DB* db;
Options options;
options.create_if_missing = true;


Status s = DB::Open(options, <DBPath>, &db);
assert(s.ok());

//main func
std::string file_data
s = db->Get(ReadOptions(), file_key, &file_data);
assert(s.ok());

//convert std::string to char*
char* buffer = (char*)malloc(file_data.size() + 1);
std::copy(file_data.begin(), file_data.end(), buffer);

//restore image
FILE* test;
fopen_s(&test, "test.jpg", "wb");
fwrite(buffer, file_data.size(), 1, test);

fclose(test);
free(buffer);
delete db;

输出图像无效,如果我将 jpg 转换为 txt,我只会得到“???”。

我在BerkeleyDB上试过同样的过程,成功恢复了镜像。(我想是因为BerkeleyDB的Dbt class) 我不知道数据在哪里崩溃了。我是不是错过了一些选项或流程...?

char* buffer = ...
db->Put(WriteOptions(), file_key, buffer);

RocksDB 应该如何知道缓冲区的长度?在此处传入 char* 时,假定它是使用 Slice(char *) 隐式转换的以 nul 结尾的 C 字符串。以 NULL 结尾的 C 字符串不能用于二进制数据,因为数据将在第一个零字节处被截断。

虽然有些 RocksDB API 不符合现代 C++ 标准(为了 API 兼容性),但它是为与 C++ 一起使用而编写的。以 NULL 结尾的 char *FILEfseek 等来自 C,在尝试与 C++ 交互时会造成很多困难。如果 bufferstd::string,这个错误将被修复,因为 Slice(std::string) 隐式转换是非常安全的。

其他错误:

  • 无法为 db->Put
  • 重新分配 s
  • 无法在 printf
  • 的错误情况下中止
  • 最好在删除前调用 DB::Close(db) 来检查状态,因为可能会出现后台错误
  • 不检查 fread
  • 中的错误

Performance/clarity 问题:

  • 在第3步中,无需创建char *buffer并将std::string file_data复制到其中。 file_data.data()file_data.size() 允许您在需要时访问底层字符缓冲区(但使用 C++ APIs 更好)。