Berkeley DB for C(2)
DB中存儲結構體
如果結構體中不包含指針,則你可以跟存儲普通類型的數據一樣,安全的使用。
存儲不帶指針的結構體示例:
#include <db.h>
#include <string.h>
typedef struct my_struct {
int id;
char familiar_name[MAXLINE]; /* MAXLINE是一個常量 */
char surname[MAXLINE];
} MY_STRUCT;
...
DBT key, data;
DB *my_database;
MY_STRUCT user;
char *fname = "David";
char *sname = "Rider";
/* 給結構體賦值*/
user.id = 1;
strncpy(user.familiar_name, fname, strlen(fname)+1);
strncpy(user.surname, sname, strlen(sname)+1);
/* 初始化key和data */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &(user.id);
key.size = sizeof(int);
data.data = &user;
data.size = sizeof(MY_STRUCT);
//調用PUT方法,賦值
my_database->put(my_database, NULL, &key, &data, DB_NOOVERWRITE);
從db中讀出結構體的數據
#include <db.h>
#include <string.h>
...
DBT key, data;
DB *my_database;
MY_STRUCT user;
/* 在使用前初始化key和data */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
/* 把結構體在內存中的地址賦給memset */
memset(&user, 0, sizeof(MY_STRUCT));
user.id = 1;
key.data = &user.id;
key.size = sizeof(int);
/* 把結構體user的地址賦給data */
data.data = &user;
data.ulen = sizeof(MY_STRUCT);
data.flags = DB_DBT_USERMEM;
my_database->get(my_database, NULL, &key, &data, 0);
//可以直接使用了,已經把取到的數據賦予了結構體
printf("Familiar name: %s/n", user.familiar_name);
printf("Surname: %s/n", user.surname);
存儲和讀取帶指針的結構體
在C中結構體中使用指針是一個很常見的想象,比如可以用一個char[]類型的指針指向一個字符串。如果想要在DB中存儲帶指針的結構頭,必須確保結構體中的所有數據在內存中是一個連續的塊。所以說在存儲結構體的時候需要對數據先進行一下轉換。
使用帶指針的結構體示例:
#include <db.h>
#include <string.h>
#include <stdlib.h>
//定義結構體
typedef struct my_struct {
int id;
char *familiar_name;//注意這裏又指針
char *surname;
} MY_STRUCT;
...
DBT key, data;
DB *my_database;
MY_STRUCT user;
int buffsize, bufflen;
char fname[ ] = "Pete";
char sname[10];
char *databuff;
strncpy(sname, "Oar", strlen("Oar")+1);
/* 先給結構體賦值 */
user.id = 1;
user.familiar_name = fname;
user.surname = sname;
/* 計算結構體中存儲的數據長度,包括指針所指向的數據的長度 */
buffsize = sizeof(int) +
(strlen(user.familiar_name) + strlen(user.surname) + 2);
//申請一個連續的內存塊
databuff = malloc(buffsize);
memset(databuff, 0, buffsize);
/* 把數據COPY到申請的內存塊中 */
memcpy(databuff, &(user.id), sizeof(int));
bufflen = sizeof(int);
//把指針所指向的數據也COPY過去,注意偏移量的計算
memcpy(databuff + bufflen, user.familiar_name,
strlen(user.familiar_name) + 1);
bufflen += strlen(user.familiar_name) + 1;
memcpy(databuff + bufflen, user.surname,
strlen(user.surname) + 1);
bufflen += strlen(user.surname) + 1;
/* 現在開始存儲 */
/* 初始化數據. */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
//設置key
key.data = &(user.id);
key.size = sizeof(int);
//設置data
data.data = databuff;//實際上傳的是內存的塊的起始地址
data.size = bufflen;//內存塊的長度
my_database->put(my_database, NULL, &key, &data, DB_NOOVERWRITE);//存儲數據
free(sname);//釋放變量
free(databuff);//釋放
從db中接手帶指針的結構體示例:
#include <db.h>
#include <string.h>
#include <stdlib.h>
typedef struct my_struct {
char *familiar_name;
char *surname;
int id;
} MY_STRUCT;
...
int id;
DBT key, data;
DB *my_database;
MY_STRUCT user;
char *buffer;
/* 初始化key和value */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
id = 1;
key.data = &id;
key.size = sizeof(int);
my_database->get(my_database, NULL, &key, &data, 0);
/*
* 很多編譯器不允許使用void類型,所以可以使用char類型來代替
* 分別指定每個指針在內存塊中的地址(需要自己根據每塊數據的大小來判斷的)
*/
buffer = data.data;
user.id = *((int *)data.data);
user.familiar_name = buffer + sizeof(int);
user.surname = buffer + sizeof(int) + strlen(user.familiar_name) + 1;