尝试使用 C++ Builder 将图像写入和读取到 SQLite
Trying write and read image to SQLite with C++ Builder
我正在使用:
- C++ 生成器 (RAD Studio 10.2)
- SQLite 3
正在尝试将 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
.
我正在使用:
- C++ 生成器 (RAD Studio 10.2)
- SQLite 3
正在尝试将 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
.