在字节数组中转换结构并存储在db中。读取db并获取字节数组以在C中重新创建结构

时间:2016-12-15 14:20:49

标签: c arrays struct filesystems gdbm

大家好抱歉,但我能找到合适的解决方案。 我正在开发一个文件系统,我将每个文件节点保存为GDBM数据库中的键值对。 我有一个具有一些属性的结构,我将其转换为字节数组

struct mystruct:

typedef struct nold{
char* name;
char* surname;
 int age;
}mystruct;

我将其转换为字节数组

dead.name="john";
dead.surname="doe";
dead.age=22;

//copy bytes of the our struct 
char buffer[sizeof(dead)]; 
memcpy(buffer, &dead, sizeof(dead));

存储在数据库中我们使用的数据结构如下:

 typedef struct {
         char *dptr;
         int  dsize;
      } datum

我填写基准结构如下:

//create a key datum
char* k="file.txt";
key.dptr=k;
key.dsize=strlen(k)+1;



//create a value datum  here I assign bytes
value.dptr=buffer;
value.dsize = sizeof(dead);

现在我将GDBM存储为键值对

然后在另一个文件中,我读取了我存储的数据并尝试将其重新转换回结构

datum result;

//read
result=gdbm_fetch(file,key);

char* bytes=result.dptr;

mystruct* reborn;

reborn=(mystruct*)bytes;


//print from our new struct
printf("%s\n",reborn->name);
printf("%s\n",reborn->surname);
printf("%d\n",reborn->age);

它打印以下内容:

E���D$�$ˈ�k����E��
$�$ˈ�k����E��
22

它设法恢复结构但是char *的数据丢失了。仅涵盖整数数据。知道为什么会这样吗?怎么解决?它不能通过存储一个字节数组来解决,将字节数组转换为十六进制或base64,并将其存储起来。

我真的在挣扎这个。请提前谢谢你。

3 个答案:

答案 0 :(得分:2)

struct中的指针只是一个指向字符数组的指针而不是字符数组本身:

typedef struct nold{
   char* name;
   char* surname;
   int age;
}mystruct;

mystruct s;
s.name = "Salam";

这将为字符串“Salam”保留一个内存空间,将字符串Salam放入并返回指向s.name的指针。

现在你正在将整个结构复制到其他东西中,你从结构地址复制sizeof(mystruct)实际上不是保持字符串“Salam”,它只是一个指向“Salam”的指针。

如果您想这样做,您必须预先为名称分配一些空格:

#define MAX_NAME_LEN    50
typedef struct nold{
   char name[MAX_NAME_LEN];
   char surname[MAX_NAME_LEN];
   int age;
}mystruct;

mystruct s;
strcpy(s.name, "Salam");

现在memcpy将起作用

mystruct d;
memcpy(&d, &s, sizeof(mystruct);

答案 1 :(得分:2)

指针值仅在特定程序的特定运行的上下文中有意义。可以编写它们并将它们读回来,但必须记住指针指定一个地址,而不是(直接)驻留 at 该地址的数据,如果地址确实有效的话对于访问它的程序。您不通过传送指针来传达进程之间的指向数据。

您可以通过将要传达的数据直接放入结构中来解决问题:

typedef struct {
     char data[MAX_DATA_SIZE];
     int  dsize;
} datum;

这种方法的缺点是你必须在数据大小上设置一个固定的上限,但在很多情况下这不是问题。如果您需要无限制的数据,那么您需要一种完全不同的方法。

答案 2 :(得分:1)

问题是name和surname是指向字符串文字的指针。所以你的struct不包含字符串本身,而是指向文字所在的数据部分的指针。只要将其复制到缓冲区,您实际上只是复制指针值。重建后,这些指针值现在指向一些不包含字符串的任意区域。

编辑:这是一个将数据传输到缓冲区的函数:

size_t copyMyStructToBuffer(mystruct *aPerson, char **buffer) {
    size_t nameLen = strlen(aPerson->name);
    size_t surnameLen = strlen(aPerson->surname);
    size_t structLen = nameLen + 1 + surnameLen + 1 + sizeof(int);
    *buffer = malloc(structLen);

    memcpy(*buffer, aPerson->name, nameLen + 1); // w/ terminator
    memcpy((*buffer)[nameLen+1], aPerson->surname, surnameLen + 1); // w/ terminator
    memcpy((*buffer)[nameLen+1+surnameLen+1], &aPerson->age, sizeof(int));

    return structLen;
}

以及如何使用它:

mystruct dead;
dead.name = "John";
dead.surname = "Doe";
dead.age = 22;
char *buff;
size_t buffLen;
buffLen = copyMyStructToBuffer(&dead, &buff);
// use buff here
free(buff);

不可否认,这段代码很难维护。