想用c++把图像的二进制数据放入RocksDB


  1. 我试图在键值存储中保存图像的二进制数据
  2. 1,读取数据使用" read"函数。第二,将其保存到RocksDB中。3、从RocksDB中获取数据,并将数据恢复为图像。
  3. 现在我不知道我是在第二步还是第三步有问题。

第二步

#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,并且我成功地恢复了映像。(我认为这是因为伯克利db的Dbt课程)我不知道哪里的数据崩溃了。我是否错过了一些选择或过程?

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

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

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

其它错误:

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

性能/清晰问题:

  • 在第三步中,不需要创建char *buffer并复制std::string file_data到它。如果需要,file_data.data()file_data.size()允许您访问底层字符缓冲区(但使用c++ api更好)。

最新更新