将包含string的结构写入二进制文件

我有一个二进制文件,其中我logging了写入其他文件的偏移量以及在该偏移量处写入的数据。 现在我将每个日志logging的结​​构定义为

struct log_record{ int offset; char *data; } struct log_record t; 

当我将logging写入文件时,我将写入该文件的数据的长度,因此在分配I分配空间之前

 t.data = (char*)malloc(sizeof(char)*strlen(buff));/*buf holds the data to be written*/ 

现在我有我正在写入文件的logging的长度…但问题是在阅读。 我如何分配一个空间结构,我读的logging和fread应该是什么大小的logging。 有一些困惑。 将gratefull帮助

您需要编写字符串的长度,因为字符串的长度是可变的。

请注意, strlen()不返回包含终止NULL的大小。

编辑 + 编辑2 (感谢亩太短)+ 编辑3 (由于亩太短)

我就是这样做的:

 t.data = (char*) malloc(sizeof(char) * strlen(buff) + 1); strcpy(t.data, buff); // ... int data_size = strlen(t.data) + 1; fwrite(&t.offset, 1, sizeof(t.offset), file); fwrite(&data_size, 1, sizeof(data_size), file); fwrite(t.data, 1, strlen(t.data) + 1, file); 

您应该避免将整个结构写入磁盘并重新读取。 你会遇到不同架构的问题,正如你所看到的,指针和可变长度的数据结构。 相反,在输出时手动整理数据,并在阅读时将其整合在一起。

在你的具体情况下,你不想写一个struct log_record ,而是写三件事:

  • offset (选择你的大小和字节顺序并坚持下去)。
  • data的长度(与上面相同的格式)。
  • data的实际字节数。

然后,当您读取数据时,读取offset并重新排列其字节以匹配本地字节顺序。 然后读取长度(与offset相同)。 现在你知道data有多大,所以你可以分配你的内存,并通过一次调用fread其从磁盘中分离出来。

哦,不要施加malloc的返回值,也不需要它,它可以隐藏问题。 相反,只是这样说:

 /* See above for how to figure out data_length. */ t.data = malloc(sizeof(char) * data_length); 

不可能将具有可变大小的结构写入二进制文件,然后再次读取它们而没有任何大小的记录。 您可以使用固定大小的char数组来代替char指针,也可以使用自定义文件格式来记录每个元素的大小(如果需要的话)。

由于我没有更好的办法,所以我写了一个小程序,希望能找到你想要的东西。 没有错误检查:)

 #include <stdio.h> #include <string.h> #include <malloc.h> typedef struct { int offset; int length; char *data; } log_record; void write_to_file(const char *filename) { log_record lr; const int num_records = 10; char buf[100]; int i; FILE *fp; fp = fopen(filename, "wb"); for(i = 0; i < num_records; ++i) { sprintf(buf, "Data entry %d goes here. Beware of size limit!", i); lr.length = strlen(buf) + 1; lr.offset = i; lr.data = malloc(sizeof(char) * lr.length); strncpy(lr.data, buf, lr.length); fwrite(&lr.offset, sizeof(lr.offset), 1, fp); fwrite(&lr.length, sizeof(lr.length), 1, fp); fwrite(lr.data, sizeof(char), lr.length, fp); free(lr.data); } fclose(fp); } void read_from_file(const char * filename) { log_record lr; int tmp; FILE *fp; fp = fopen(filename, "rb"); while (feof(fp) == 0) { tmp = fgetc(fp); if(tmp != EOF) { ungetc(tmp, fp); fread(&lr.offset, sizeof(int), 1, fp); fread(&lr.length, sizeof(int), 1, fp); lr.data = malloc(sizeof(char) * lr.length); fread(lr.data, sizeof(char), lr.length, fp); free(lr.data); } } fclose(fp); } int main(int argc, char *argv[]) { write_to_file("temp.bin"); read_from_file("temp.bin"); return 0; }