代码之家  ›  专栏  ›  技术社区  ›  deostroll

读取文件并填充结构

  •  4
  • deostroll  · 技术社区  · 14 年前

    typedef struct myStruct{
        int a;
        char* c;
        int f;
    } OBJECT;
    

    我可以填充这个对象并将其写入文件。但是我无法读取其中的char*c值……在尝试读取时,它会给我一个分段错误。我的代码有什么问题吗:

    //writensave.c
    
    #include "mystruct.h"
    #include <stdio.h>
    #include <string.h>
    
    
    #define p(x) printf(x)
    
    int main()
    {
        p("Creating file to write...\n");
        FILE* file = fopen("struct.dat", "w");
        if(file == NULL)
        {
            printf("Error opening file\n");
            return -1;
        }
    
        p("creating structure\n");
        OBJECT* myObj = (OBJECT*)malloc(sizeof(OBJECT));
        myObj->a = 20;
        myObj->f = 45;
        myObj->c = (char*)calloc(30, sizeof(char));
        strcpy(myObj->c, 
            "This is a test");
        p("Writing object to file...\n");
        fwrite(myObj, sizeof(OBJECT), 1, file);
        p("Close file\n");
        fclose(file);
        p("End of program\n");
        return 0;       
    }
    

    以下是我试图阅读的方式:

    //readnprint.c
    #include "mystruct.h"
    #include <stdio.h>
    #define p(x) printf(x)
    int main()
    {   
        FILE* file = fopen("struct.dat", "r");
        char* buffer;
        buffer = (char*) malloc(sizeof(OBJECT));
        if(file == NULL)
        {
            p("Error opening file");
            return -1;
        }
    
        fread((void *)buffer, sizeof(OBJECT), 1, file);
        OBJECT* obj = (OBJECT*)buffer;
        printf("obj->a = %d\nobj->f = %d \nobj->c = %s",
            obj->a,
            obj->f,
            obj->c);
        fclose(file);
        return 0;
    }
    
    5 回复  |  直到 14 年前
        1
  •  2
  •   dash-tom-bang    14 年前

    编写对象时,将指针值写入文件,而不是指向信息。

    你需要做的是 只是写/写你的整个结构,而不是一次一个领域。fwrite a和f就像处理对象一样,但接下来需要对字符串执行一些特殊的操作。尝试fwrite/fread的长度(在数据结构中没有表示,这很好),然后fwrite/fread字符缓冲区。当然,在读的时候你需要分配它。

        2
  •  2
  •   bta    14 年前

    typedef struct myStruct{
        int a;
        char c[30];
        int f;
    } OBJECT;
    

    否则,您只需存储一个指向动态分配的内存的指针,该内存将在程序退出时被销毁(因此,当您稍后检索此指针时,该地址是毫无价值的,并且很可能是非法访问的)。

        3
  •  1
  •   Stu Mackellar    14 年前

    你保存的是一个指向字符的指针,而不是字符串本身。当您尝试重新加载文件时,您正在使用不同地址空间的新进程中运行,并且该指针不再有效。您需要按值保存字符串。

        4
  •  1
  •   Sparky    14 年前

    我想添加一个关于潜在可移植性问题的注释,它可能取决于数据文件的计划使用而可能存在,也可能不存在。

    如果要在不同端的计算机之间共享数据文件,则需要为非字符类型(int、short、long、long long…)配置文件到主机和主机到文件转换器。此外,使用 标准高度 (int16_t,int32_t,…)以保证您想要的大小。

    但是,如果数据文件不会在任何地方移动,则忽略这两点。

        5
  •  1
  •   Thomas Matthews    14 年前

    这个 char * 你的结构领域被称为 . 编写此字段时,需要一个确定文本长度的方法。两种流行的方法是:
    一。先写大小

    先写大小

    优点:通过块读取可以更快地加载文本。
    缺点:需要两次读取,长度数据需要额外空间。

    struct My_Struct
    {
       char * text_field;
    };
    
    void Write_Text_Field(struct My_Struct * p_struct, FILE * output)
    {
      size_t text_length = strlen(p_struct->text_field);
      fprintf(output, "%d\n", text_length);
      fprintf(output, "%s", p_struct->text_field);
      return;
    }
    
    void Read_Text_Field(struct My_STruct * p_struct, FILE * input)
    {
      size_t text_length = 0;
      char * p_text = NULL;
      fscanf(input, "%d", &text_length);
      p_text = (char *) malloc(text_length + sizeof('\0'));
      if (p_text)
      {
         fread(p_text, 1, text_length, input);
         p_text[text_length] = '\0';
      }
    }
    

    书写终端字符 在这种方法中,文本数据后面跟着一个“终端”字符。与C语言字符串非常相似。 优点:首先需要的空间比尺寸小。

    固定大小字段
    而不是使用 char* char [N] 其中n是字段的最大大小。 优点:固定大小的记录可以作为块读取。 使文件中的随机访问更容易。 字段太小时出现问题。

    将数据结构写入文件时,应 考虑使用数据库 以及调试 经过测试 .