【问题标题】:Writing and reading (fwrite - fread) structures with pointers使用指针写入和读取 (fwrite - fread) 结构
【发布时间】:2012-01-25 23:21:09
【问题描述】:

我正在做一个邮箱项目,我有这两种结构:

结构 mmbox_mail

struct mmbox_mail {
  char *sender, *recipient; 
  char *obj, *date;
  char flags; 
  size_t size; 
};

ma​​il_t

typedef struct{
  struct mmbox_mail info;
  void *body;
  void *next;
} mail_t;

我无法修改结构的字段,因为我需要可变数据(为此我使用了 char* 而不是 char[])。

每个 mail_t 结构都是一个邮件。我需要将用户的每封邮件保存在一个文件中,可以是二进制文件或文本文件(但我认为使用二进制文件更好,因为我的 void* 正文很难以纯文本格式保存。

我尝试过这样做,但似乎不起作用:

while(mailtmp != NULL){
  fwrite(mailtmp, sizeof(mail_t), 1, fp);

  /* next mail */
  mailtmp=mailtmp->next;
}
while(mailtmp != NULL){  /* i have a list of mails and i use a mailtmp pointer to save each mail */

你能帮帮我吗?我试图到处搜索,但从未找到有人要求保存两个结构,一个在另一个内部。

【问题讨论】:

    标签: c fwrite structure fread


    【解决方案1】:

    当然,这对字符串不起作用,它将复制指针的大小(通常为 4 个字节)。我在这里看到 3 个选项:

    1. 序列化数据、二进制文件 (http://en.wikipedia.org/wiki/Serialization)。
    2. 创建将数据存储在文本文件中的格式。
    3. 使用 XML/JSON 等标记语言

    在任何情况下,您都需要遍历结构的每个字段才能将其写入数据文件。至于读取,在前两种情况下,您必须完全按照写入数据的顺序进行读取,在第三种情况下,您将能够以任何顺序独立读取字段。

    如果您选择第一种方法,则为每个字符串 (char *) 字段也写入零终止字节,以便您在读回时始终知道它的结束位置。

    【讨论】:

    • 好的,我不能使用 XML/JSON,ecc .. 因为我不知道 :( 我试图创建一种格式来存储数据(比如保存发件人然后保存收件人然后保存数据, ecc ...) 但它似乎效率不高.. (任何建议都被接受.. :) ) 顺便说一句,我会寻找序列化.. :)
    • 序列化数据的想法是您以与读取数据完全相同的顺序写入部分。所以,e。 G。如果您需要使用姓名、年龄、地址存储客户,您将打开文件而不是 EOF:写入名称(零终止字节),写入年龄(整数,4 个字节),写入地址(零终止字节) .读取将是:打开文件,而不是 EOF:读取字符直到零字符进入缓冲区(名称),读取 4 个字节(年龄),读取字符直到零字符进入缓冲区(地址)。
    • 好的。我得到了它。今天我再次写了这个例程,我会和你保持联系。 :D(真的很抱歉我的英语不好.. :()非常感谢!:D
    • 过去对序列化可能性的讨论:stackoverflow.com/questions/371371/…
    • 另外,如果你熟悉 SQL,你会考虑使用 libsqlite 吗?尤其是在有大量数据的情况下。
    【解决方案2】:

    您正在做的是将 mail_t 的文字二进制表示保存到文本文件中,这只是一堆指针。你想做的事情是:

    fprintf( fp, "To: %s\nFrom: %s\n....\nContents: %*s\n\n", mailtmp->info.recipient, mailtmp->info.sender, mailtmp->info.size, mailtmp->body );
    

    这会将指向的值呈现为字符串并将其保存到文件中。在应用程序关闭后,指向应用程序持有的内存位置的指针对大多数人来说有点没用;)

    编辑:“你能帮我吗?我试着到处搜索,但我从来没有找到有人要求保存两个结构,一个在另一个里面。”

    如果您只有一流的数据类型,例如整数或浮点数等,您的方法将完美运行。但是,由于您使用的是第二类类型,即 char 和 void 数组,因此您必须实际指定应如何保存指向的数据。

    【讨论】:

    • 我试过这种方式,但我发现一个问题是:如何以纯文本形式保存 void *body?我的意思是,电子邮件的正文可能是各种数据,所以我不能将其保存为纯文本.. 还是没有? O.o
    • 嗯,电子邮件格式本质上是纯文本。附加到电子邮件的二进制文件经过 base64 处理,以允许通过纯文本协议进行传输。您可以编写一个解析器来从电子邮件中提取实际文本;您可以解析文件,对它们进行 de-base64 处理,然后将它们 fwrite() 写入文件;你可以做任何你想做的事。但是,您的问题范围并未涵盖此内容,完全由您决定如何处理。
    • 很抱歉,我的项目是“自制”项目,我想在本地运行,而不是远程运行.. 所以我正在寻找不那么复杂的东西 :) 将来我会实现使其远程运行的功能,但目前我想让它在本地运行.. :) 无论如何,谢谢! :D
    • 如果你愿意,你可以加入讨论,带着 dimir 的回答.. :) 如果你有任何想法,我在这里准备好阅读! :)
    【解决方案3】:

    好吧,你将结构的指针存储到文件中。而不是它指向的数据。即使你存储了你想要的结构。很难从文件中获取它。我认为您需要像google protocal buffer 这样的序列化组件。然后您可以编写一个适配器,将结构转换为 probuf 对象,然后将其存储到文件中。当您需要时,将其恢复。希望它对您有所帮助:)

    【讨论】:

    • 非常感谢您的帮助! :D 但是,我想我已经解决了底米尔的回答.. 我说“我认为”,因为我不确定..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 2018-03-12
    相关资源
    最近更新 更多