我正在读取600,000张图像的目录,并希望将这些图像存储在Sqlite DB中。数据库结构只是ID,IMAGE(blob)。
我不精通C ++,所以想办法解决。
首先,我打开数据库文件并设置prepare语句等
int rc = sqlite3_open_v2(filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
char* errorMessage;
sqlite3_exec(db, "PRAGMA synchronous=OFF", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA count_changes=OFF", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA journal_mode=MEMORY", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errorMessage);
sqlite3_exec(db, "PRAGMA cache_size=1", NULL, NULL, &errorMessage);
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &errorMessage);
char const *szSQL = "INSERT INTO images (image) VALUES (?);";
int rc = sqlite3_prepare_v2(db, szSQL, -1, &stmt, NULL);
if( rc != SQLITE_OK ) {
printf("PREPARE FAILED. EXITING\n");
exit(0);
}
然后有一个while循环遍历目录中的所有文件。要将图像读取为char *(用于blob),我使用以下代码:
char text[10] = {'\0'};
struct stat s;
int status = stat(fullimagepath.c_str(), &s);
int fd = open(fullimagepath.c_str(), O_RDONLY);
if (fd == -1)
{
perror("Error opening file for reading");
exit(1);
}
char *fileContent = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
下面的代码也在每次迭代上运行,在该迭代中,它绑定blob并尝试插入
int retVal = sqlite3_bind_blob(stmt, 1, fileContent, s.st_size, NULL);
if (retVal != SQLITE_OK) {
fprintf(stderr, "ERROR %s %s\n", fullimagepath.c_str(), sqlite3_errmsg(db));
sqlite3_finalize(stmt);
sqlite3_close(db);
exit(1);
}
retVal = sqlite3_step(stmt);
if (retVal != SQLITE_DONE && retVal != SQLITE_ROW) {
sqlite3_finalize(stmt);
sqlite3_close(db);
fprintf(stderr, "ERROR %d\n", retVal);
exit(1);
}
fprintf(stderr, "1f2 %s\n", fullimagepath.c_str());
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
其中fullimagepath是每次图像的完整路径(以上内容在while循环中循环访问目录中的文件)。
完成完整目录后,我们将运行提交并关闭数据库。
sqlite3_exec(db, "COMMIT", NULL, NULL, &errorMessage);
sqlite3_finalize(stmt);
sqlite3_close(db);
我遇到的问题是,运行了多个文件后,它以segmentation fault
停止。
据我在各种试验中所知,我将Blob更改为文本和其他测试,只有在尝试插入Blob时才会发生这种情况。
有人可以指出正确的方向来解决这个问题吗?
[在小于10,000张图片的较小目录上运行时,它可以正常工作。或者,如果您需要更多信息,请提出建议。
谢谢。
我怀疑您会占用我们的内存,所以请检查一下。
char *fileContent = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED | MAP_POPULATE , fd, 0);
if (!fileContent) {
perror("Error mapping file");
exit(1);
}
close(fd);
我终于在@Surt之后的第一个评论中提到了“您在哪里映射”这个问题。我不知道这是什么意思,在其他地方进行大量搜索后,我注意到一条评论提到了这一点。多玩一点,意识到这很关键。放置以下
status = munmap(fileContent, s.st_size);
sqlite3_reset(stmt);
感谢那些对正确方向的指针发表意见的人。非常感谢。