想用C++将图像的二进制数据放入RocksDB
Want to put binary data of images into RocksDB in C++
- 我正在尝试在键值存储中保存图像的二进制数据
- 1、使用“fread”函数读取数据。 2、保存到RocksDB中。 3、从RocksDB中获取数据,并将数据还原为图片形式。
- 现在不知道是不是第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 *
、FILE
、fseek
等来自 C,在尝试与 C++ 交互时会造成很多困难。如果 buffer
是 std::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 更好)。
- 我正在尝试在键值存储中保存图像的二进制数据
- 1、使用“fread”函数读取数据。 2、保存到RocksDB中。 3、从RocksDB中获取数据,并将数据还原为图片形式。
- 现在不知道是不是第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 *
、FILE
、fseek
等来自 C,在尝试与 C++ 交互时会造成很多困难。如果 buffer
是 std::string
,这个错误将被修复,因为 Slice(std::string)
隐式转换是非常安全的。
其他错误:
- 无法为
db->Put
重新分配 - 无法在
printf
的错误情况下中止
- 最好在删除前调用
DB::Close(db)
来检查状态,因为可能会出现后台错误 - 不检查
fread
中的错误
s
Performance/clarity 问题:
- 在第3步中,无需创建
char *buffer
并将std::string file_data
复制到其中。file_data.data()
和file_data.size()
允许您在需要时访问底层字符缓冲区(但使用 C++ APIs 更好)。