最も簡単な方法は、プロジェクトに単一の .c ファイルとして統合されるsqlite db にBLOB として格納することです。BLOB にアクセスする 2 つの異なる方法を示す C ファイルの例を参照してください。1 つはバインドを使用し、もう 1 つは BLOB API を使用します。
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <unistd.h>
#include <libgen.h>
#include "sqlite3.h"
sqlite3 *db;
int error(char *msg) {
fprintf(stderr, "ERROR: %s\n", msg);
if(db)
sqlite3_close(db);
exit(1);
}
int gettype(char **imgtype, int columns, char **colval, char **colname) {
int col;
if(columns!=1)
return 1;
snprintf((char *)imgtype, 4, "%s", colval[0]);
return 0;
}
int getrowid(sqlite3_int64 *rowid, int columns, char **colval, char **colname) {
int col;
if(columns!=1)
return 1;
*rowid=(int)strtol(colval[0], NULL, 10);
return 0;
}
int main(int argc, char **argv) {
enum { PROG, FUNC, TABLE, NAME };
sqlite3_blob *dblob;
char sqlcmd[1024];
sqlite3_int64 rowid=0;
sqlite3_stmt *stmt;
char *zErrMsg=0;
char filename[1024];
char outname[1024];
char imgtype[4];
FILE *fblob;
char *blobmem;
long blobsize;
if(argc!=4)
error("usage: blob <get|put> <table> <filename>");
if(sqlite3_open(DATABASE, &db))
error((char*)sqlite3_errmsg(db));
sqlite3_busy_timeout(db, TIMEOUT);
// using bind api
if(strcmp(argv[FUNC], "put")==0) {
snprintf(filename, 1024, "%s", basename(argv[NAME]));
strtok(filename, ".");
snprintf(imgtype, 4, "%s", strtok(NULL, "."));
if(!strlen(imgtype) || !(strcasecmp(imgtype, "gif")==0 || strcasecmp(imgtype, "jpg")==0 || strcasecmp(imgtype, "png")==0))
error("wrong extension / img type");
fblob=fopen(argv[NAME], "r");
if(fblob==NULL)
error("file not found");
fseek(fblob, 0L, SEEK_END);
blobsize=ftell(fblob);
if(!blobsize)
error("wrong file size");
blobmem=malloc(blobsize);
if(!blobmem)
error("unable to allocate memory");
rewind(fblob);
if(fread(blobmem, blobsize, 1, fblob)!=1)
error("unable to read file");
fclose(fblob);
snprintf(sqlcmd, 1024, "delete from '%s' where name like '%s';", argv[TABLE], filename);
if(sqlite3_exec(db, sqlcmd, NULL, NULL, &zErrMsg)!=SQLITE_OK)
error(zErrMsg);
snprintf(sqlcmd, 1024, "insert into '%s'(name, type, data) values(?, ?, ?);", argv[TABLE]);
if(sqlite3_prepare_v2(db, sqlcmd, -1, &stmt, 0)!=SQLITE_OK)
error((char*)sqlite3_errmsg(db));
sqlite3_bind_text(stmt, 1, filename, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, imgtype, -1, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 3, blobmem, blobsize, SQLITE_STATIC);
if(sqlite3_step(stmt)!=SQLITE_DONE)
error((char*)sqlite3_errmsg(db));
if(sqlite3_finalize(stmt)!=SQLITE_OK)
error((char*)sqlite3_errmsg(db));
free(blobmem);
}
// using blob api
else if(strcmp(argv[FUNC], "get")==0) {
snprintf(filename, 1024, "%s", argv[NAME]);
strtok(filename, ".");
snprintf(sqlcmd, 1024, "select rowid from '%s' where name like '%s';", argv[TABLE], filename);
if(sqlite3_exec(db, sqlcmd, (void *)&getrowid, &rowid, &zErrMsg)!=SQLITE_OK)
error(zErrMsg);
if(!rowid)
error("not found");
snprintf(sqlcmd, 1024, "select type from '%s' where name like '%s';", argv[TABLE], filename);
if(sqlite3_exec(db, sqlcmd, (void *)&gettype, &imgtype, &zErrMsg)!=SQLITE_OK)
error(zErrMsg);
if(!strlen(imgtype) || !(strcasecmp(imgtype, "gif")==0 || strcasecmp(imgtype, "jpg")==0 || strcasecmp(imgtype, "png")==0))
error("wrong extension / img type");
if(sqlite3_blob_open(db, "main", argv[TABLE], "data", rowid, 0, &dblob)!=SQLITE_OK)
error((char*)sqlite3_errmsg(db));
blobsize=sqlite3_blob_bytes(dblob);
if(!blobsize)
error("image is 0 bytes in size");
blobmem=malloc(blobsize);
if(!blobmem)
error("unable to allocate memory");
if(sqlite3_blob_read(dblob, blobmem, blobsize, 0)!=SQLITE_OK)
error("unable to read image");
sqlite3_blob_close(dblob);
snprintf(outname, 1024, "%s.%s", filename, imgtype);
fblob=fopen(outname, "w");
if(fblob==NULL)
error("unable to open target file");
if(fwrite(blobmem, blobsize, 1, fblob)!=1)
error("unable to write to target file");
fclose(fblob);
free(blobmem);
}
else
error("wrong usage");
sqlite3_close(db);
return 0;
}
画像とともに ID を保存するには、同じテーブルに別の列を作成するだけです。