尝试使用 C++ Builder 将图像写入和读取到 SQLite

Trying write and read image to SQLite with C++ Builder

我正在使用:

正在尝试将 PNG 图像保存到 SQLite 库,然后将其取回。我已经看了三天的论坛,但找不到解决方案。

这是我的代码:

图片写代码

AnsiString Insert_data;
UnicodeString Path;
int rc,filesize,rowid;
sqlite3 *db;
sqlite3_stmt *insert_stmt;
sqlite3_blob *blob;

if(OpenDialog1->Execute())
{
    Memo1->Lines->Add(OpenDialog1->FileName);
    Image1->Picture->LoadFromFile(OpenDialog1->FileName);
}
sqlite3_open16(base_name.c_str(), &db);

Path = OpenDialog1->FileName;
TFileStream *f = new TFileStream(Path, fmOpenRead);
filesize = f->Size;
Memo1->Lines->Add("Вес файла : " + (String)filesize);
f->Position = 0;
Insert_data = "INSERT INTO images(id, pic_id, picture_name, data) VALUES (?, ?, ?, ?);";
rc = sqlite3_prepare_v2(db, Insert_data.c_str(), -1, &insert_stmt, NULL);
if(rc != SQLITE_OK)
{
    Memo1->Lines->Add(sqlite3_errmsg(db));
    sqlite3_close(db);
}
sqlite3_bind_int(insert_stmt, 1, 1);
sqlite3_bind_int(insert_stmt, 2, 1);
Insert_data = OpenDialog1->FileName;
sqlite3_bind_text(insert_stmt, 3, Insert_data.c_str(), -1, 0);
sqlite3_bind_zeroblob(insert_stmt, 4, filesize);
// sqlite3_bind_blob(insert_stmt,4,f, f->Size,SQLITE_STATIC); // That doesn't work too
rc = sqlite3_step(insert_stmt);
if(rc != SQLITE_DONE)
{
    Memo1->Lines->Add("Insert statement didn't work");
    Memo1->Lines->Add(sqlite3_errmsg(db));
    sqlite3_close(db);
    return;
}
sqlite3_reset(insert_stmt);

rowid = sqlite3_last_insert_rowid(db);

rc = sqlite3_blob_open(db, "main", "images", "data", rowid, 1, &blob);
if(rc != SQLITE_OK)
{
    Memo1->Lines->Add(sqlite3_errmsg(db));
    sqlite3_close(db);
    return;
}
Memo1->Lines->Add("size of BLOB : " + (String)sqlite3_blob_bytes(blob));


rc = sqlite3_blob_write(blob, f, f->Size, 0);
if(rc != SQLITE_OK)
{
    Memo1->Lines->Add("Error write " + IntToStr(error));
    Memo1->Lines->Add(sqlite3_errmsg(db));
}
rc = sqlite3_blob_close( blob ); 
if(rc != SQLITE_OK)
{
    Memo1->Lines->Add("Error close " + IntToStr(error));
    Memo1->Lines->Add(sqlite3_errmsg(db));
}

图片读取代码

sqlite3 *db; 
sqlite3_blob *data; 
int rc, bytes; 
int error = -100;

sqlite3_open("game_data",&db); 
rc = sqlite3_blob_open(db,"main","images","data",1,0,&data); 
if(rc != SQLITE_OK)
{
    Memo1->Lines->Add(sqlite3_errmsg(db));
    sqlite3_close(db);
    return;
}

bytes = sqlite3_blob_bytes(data); 
char *zBlob = (char *) malloc(bytes); 
error = sqlite3_blob_read(data,zBlob,bytes,0); 
if(error != SQLITE_OK)
{
    Memo1->Lines->Add("Error open " + IntToStr(error));
    Memo1->Lines->Add(sqlite3_errmsg(db));
}

TMemoryStream *ms = new TMemoryStream(); 
ms->Write(zBlob, bytes);
ms->Position = 0;

Memo1->Lines->Add("read: " + IntToStr(bytes));
//Image1->Picture->LoadFromStream(ms); // error
ms->SaveToFile("123.png");

sqlite3_close(db);
//delete []ms;

好像是写入和读取,字节大小是一样的,但是生成的123.png文件不是图片读取的。某处丢失了一些东西,我无法理解是什么问题。

我认为问题出在这一行:

rc = sqlite3_blob_write(blob, f, f->Size, 0);

其中 f 是 TFileStream *。 SQLite 需要一个指向内存缓冲区的指针来复制字节,因此您实际上是在复制 TFileStream 对象的内容而不是文件内容。我认为您应该先将 TFileStream 完全读入内存缓冲区,然后将指向 that 的指针传递给 sqlite3_write_blob.