Попытка написать и прочитать изображение в SQLite с помощью C ++ Builder - PullRequest
0 голосов
/ 01 апреля 2020

Я использую:

  • C ++ Builder (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 не читается как рисунок. Что-то где-то потеряно, я не могу понять, в чем проблема.

1 Ответ

0 голосов
/ 01 апреля 2020

Я думаю, что проблема в этой строке:

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

, где f - это TFileStream *. SQLite ожидает указатель на буфер памяти для копирования байтов, поэтому вы фактически копируете содержимое объекта TFileStream вместо содержимого файла. Я думаю, что вы должны сначала прочитать TFileStream в буфер памяти и передать указатель на , что на sqlite3_write_blob.

...