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

3
我有一个二进制文件,记录了写入其他文件发生的偏移量以及在该偏移量处写入的数据。现在我定义每个日志记录的结构为:
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个回答

3
你需要将字符串的长度作为变量来写。请注意,strlen()不会返回包括空终止符在内的字符串大小。
编辑+编辑2(感谢mu is too short)+编辑3(感谢mu is too short)
以下是我的做法:
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);

@Donotalo..对不起,我没有听懂你的意思。 - Lipika Deka
@mu 太短了:我提出的不是编辑!感谢指出我的错误。我将进行编辑。 - Donotalo
@mu太短了:已检查。 :) - Donotalo

3
你应该避免将整个结构体写入磁盘并重新读取。你会遇到不同架构的问题,以及指针和变长数据结构的问题,正如你所注意到的一样。相反,当输出时手动编组数据,并在读取时重新组合它们。
在你的特定情况下,你需要写三件事情,而不是写一个 "struct log_record":
1. 偏移量(选择你的大小和字节顺序,并坚持不变)。 2. “数据”的长度(以与上述相同的格式)。 3. 实际的“数据”字节。
然后,在你读回数据时,读取“偏移量”,并重新排列其字节以匹配本地字节顺序。然后读取长度(以与“偏移量”相同的方式)。现在你知道了“数据”的大小,因此可以分配内存,并通过单个调用"fread"从磁盘中读取它。
噢,不要将"malloc"的返回值强制转换,这没有必要,而且可能会隐藏问题。相反,只需说:
/* See above for how to figure out data_length. */
t.data = malloc(sizeof(char) * data_length);

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接