简体   繁体   English

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

[英]Convert struct in byte array and store in db. Read db and get byte array to recreate the struct in C

Hello everyone sorry for asking but I could find any appropriate solution. 大家好,很抱歉询问,但我可以找到任何适当的解决方案。 I am working on a file system where I save each file node as key-value pair in a GDBM database. 我正在一个文件系统上,将每个文件节点作为键值对保存在GDBM数据库中。 I have a struct which has some attributes and I convert this to a byte array 我有一个具有一些属性的结构,并将其转换为字节数组

struct mystruct: struct mystruct:

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

I convert it as following to a byte array 我将其转换为以下字节数组

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

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

to store in a database we use a datum structure which is as following: 为了存储在数据库中,我们使用如下数据结构:

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

I fill the datum structure as following: 我按如下所示填充基准结构:

//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);

Now I store in GDBM as key-value pair 现在我将GDBM作为键值对存储

Then in another file I read the data I store and try to recast it back to a struct 然后在另一个文件中,我读取了存储的数据,并尝试将其重铸回结构

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);

It prints the following: 它打印以下内容:

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

It manages to bring back the struct but data of char* is lost. 它设法恢复结构,但char *的数据丢失。 Only the integer data is covered. 仅覆盖整数数据。 Any idea why that happening? 知道为什么会这样吗? How to solve it? 怎么解决呢? It it cant be solved by storing a byte array what about converting the byte array to hex or base64 and store it as such. 通过存储字节数组无法解决将字节数组转换为十六进制或base64并将其原样存储的问题。

I really am struggling with this one.Thank you in advance. 我真的很挣扎,谢谢。

A pointer inside struct is just a pointer to character array not the character array itself: struct内部的指针只是指向字符数组的指针,而不是字符数组本身:

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

mystruct s;
s.name = "Salam";

This will reserver a memory space for string "Salam", put string Salam into and return back the pointer to s.name. 这将为字符串“ Salam”保留一个存储空间,将字符串Salam放入其中并返回指向s.name的指针。

now you're copying entire struct into something other, youre copying from struct address with sizeof(mystruct) which isn't hold string "Salam" actually, it just holds a pointer to "Salam". 现在,您要将整个结构复制到其他结构中,即从具有sizeof(mystruct)的结构地址复制,该地址实际上不包含字符串“ Salam”,它仅包含指向“ Salam”的指针。

If you want to do this way, you have to preallocate some space for name : 如果要这样做,则必须为name预分配一些空间:

#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");

now memcpy will work 现在memcpy将工作

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

Pointer values are meaningful only in the context of a specific run of a specific program. 指针值仅在特定程序的特定运行中才有意义。 It is possible to write them and read them back, but it is essential to remember that a pointer designates an address, not (directly) the data residing at that address, if indeed the address is valid at all for the program accessing it. 它可以写他们,读他们回来,但要记住,一个指向指定的地址,不(直接)的数据驻留该地址,如果确实的地址是有效的,在所有程序访问它,它是必不可少的。 You do not convey the pointed-to data between processes by conveying the pointer. 您不会通过传递指针来在进程之间传递指向的数据。

You could perhaps solve the problem by putting the data you want to convey directly into the struct: 您也许可以通过将要传递的数据直接放入结构中来解决问题:

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

The drawback of this approach is that you have to put a fixed upper bound on the size of the data, but in many cases that's not a problem. 这种方法的缺点是必须在数据大小上设置固定的上限,但是在很多情况下这不是问题。 If you need unbounded data, then you need an altogether different approach. 如果您需要无限制的数据,那么就需要一种完全不同的方法。

The problem is that name and surname are pointers to string literals. 问题在于名称和姓氏是指向字符串文字的指针。 So your struct does not contain the string itself but rather pointers to the data section where the literals reside. 因此,您的结构本身不包含字符串,而是指向文字所在的数据部分的指针。 As soon as you copy that to your buffer, you are in fact simply copying the pointer values. 只要将其复制到缓冲区中,实际上就是在复制指针值。 Upon reconstruction, those pointer values would now point to some arbitrary area that don't contain your strings. 重建后,这些指针值现在将指向不包含您的字符串的任意区域。

EDIT: Here's a function that transfers the data to a buffer: 编辑:这是一个将数据传输到缓冲区的函数:

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;
}

And how you can use it: 以及如何使用它:

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);

Admittedly though, this code is difficult to maintain. 当然,该代码很难维护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM