我有一个二进制文件,我在其中记录写入其他文件的偏移量以及在该偏移量处写入的数据。现在我将每个日志记录的结构定义为
struct log_record{
int offset;
char *data;
}
struct log_record t;
当我将记录写入文件时,我有足够的数据写入文件,因此在分配之前我将空间分配为
t.data = (char*)malloc(sizeof(char)*strlen(buff));/*buf holds the data to be written*/
现在我有了写入文件的记录的长度......但问题是在阅读时。如何为我读取记录的结构和fread中的空间分配空间应该是记录的大小。有点困惑。 会感激不尽的帮助
答案 0 :(得分:3)
你需要写字符串的长度,因为字符串的长度是可变的。
请注意,strlen()
不会返回包括终止NULL的大小。
编辑 + 编辑2 (感谢mu太短了)+ 编辑3 (感谢mu太短了)
我就是这样做的:
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);
答案 1 :(得分:3)
您应该避免将整个结构写入磁盘并再次读取它们。您将遇到不同体系结构的问题,并且正如您所注意到的那样,指针和可变长度数据结构。相反,在输出时手动编组数据并在读取时将其重新组合在一起。
在您的具体情况下,您不想写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);
答案 2 :(得分:0)
不可能将具有可变大小的结构写入二进制文件,然后再次读取它们而不记录其大小。您可以使用具有固定大小的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;
}