将包含字符串的结构写入二进制文件

时间:2011-06-30 06:45:45

标签: c linux binaryfiles

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

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中的空间分配空间应该是记录的大小。有点困惑。  会感激不尽的帮助

3 个答案:

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