【问题标题】:Writing data from a linked list to a binary file using fwrite.使用 fwrite 将数据从链表写入二进制文件。
【发布时间】:2013-10-17 19:42:36
【问题描述】:

我不知道如何处理这项任务。

我特地得用fwrite,但是我的问题是我不知道怎么把不同的文件类型(char[],int,double)写成二进制文件的一行,递增,然后写下一个链表中的大量数据会增加它.....等等。

下面的代码将链表(Data)中的数据写入文本文件,转到下一行并重复该过程,直到列表的最后一个元素被写入文本文件。

我需要编写一个具有相同原理但使用 fwrite 将链表中的数据写入二进制文件的函数。有什么想法吗?

void WriteTextFile(ListDataType *Data, int numEl)
{
    FILE *textfile;

    char name[50];

    printf("\n\nWhat would you like to call the text file in which the data will be stored?\nNB remember to add \".txt\" after your chosen name!!!\nENTER NAME NOW>>");
    scanf("%s", name);

    textfile = fopen(name, "w+");

    do
    {
        fprintf(textfile, "%s %d %d %.2lf %.2lf %.2lf %.2lf\n", Data->component.name, Data->component.int1, Data->component.int2, Data->component.double1, Data->double2, Data->double3, Data->double4 );
        Data = Data->nextPtr;
    }while(Data != NULL);

    fclose(textfile);
}

【问题讨论】:

  • 只要是简单数据类型的结构,就可以简单的把fwrite(Data, 1, sizeof(ListDataType));
  • Data->component.name是结构中的完整字符串,还是动态分配的字符串指针?
  • @mbratch 它是一个动态分配的字符串指针。

标签: c


【解决方案1】:

由于您有一项可变长度数据(动态分配的字符串指针),您必须决定如何在二进制文件中管理它。您可以在输出的结构中为名称留出固定长度的空间。或者您可以编写一个以零结尾的字符串并以这种方式管理它。我会选择第二种情况,因为它更符合动态字符串。

这有点冗长,因为问题陈述中没有给出结构的性质。因此,以下内容将以任意顺序处理结构元素。

void WriteBinaryFile(ListDataType *Data, int numEl)
{
    FILE *bin_file;

    char name[50];

    printf("\n\nWhat would you like to call the binary file in which the data will be stored?\n"
    printf("NB remember to add \".txt\" after your chosen name!!!\nENTER NAME NOW>>");
    scanf("%s", name);

    bin_file = fopen(name, "wb+");

    do
    {
        //NOTE: include terminating zero in the string output; assumes single-byte chars
        fwrite(Data->component.name, strlen(Data->component.name)+1, 1, bin_file);
        fwrite(&Data->component.int1, sizeof(Data->component.int1), 1, bin_file);
        fwrite(&Data->component.int2, sizeof(Data->component.int2), 1, bin_file);
        fwrite(&Data->component.double1, sizeof(Data->component.double1), 1, bin_file);
        fwrite(&Data->component.double2, sizeof(Data->component.double2), 1, bin_file);
        fwrite(&Data->component.double3, sizeof(Data->component.double3), 1, bin_file);
        fwrite(&Data->component.double4, sizeof(Data->component.double4), 1, bin_file);
        Data = Data->nextPtr;
    } while(Data != NULL);

    fclose(bin_file);
}

如果程序需要回读它,它会从读入名称开始并读取字符,直到找到0。然后它会根据数据类型读取其他元素。对于每个编写的结构,都会重复该过程。不过,这不一定是可移植的。您必须注意 int 时间的大小等。

【讨论】:

    【解决方案2】:

    你想做一些类似的事情:

    fwrite (Data , sizeof(ListDataType), 1, fileHandle);
    

    这将从数据点的任何位置开始写入 sizeof(ListDataType) 个字节。如果您的 Data 对象中有任何指针 - 您需要定义一个新结构,将值复制到该结构,然后编写新结构。

    如果你不能定义动态字符串的最大长度,那么你可以定义一个包含字符串长度的结构——先写结构,然后写字符串——这样你就知道要读回多少字节。无论哪种方式,结构都是读取和写入 bin 文件的最佳方式。

    好的 - 带有示例的编辑 ...

    如果您将组件结构定义为:

        typedef struct Component_Struct
        {
            int int1;
            int int2;
            double double1;
            double double2;
            double double3;
            double double4;
            int nameLen;
            char* name;
        }
        COMPONENT, *LPCOMPONENT;
    

    注意额外的 nameLen - 当您将值分配给结构时填写此值。

    然后在你的 write 函数中:

          FILE * pFile;
          pFile = fopen ("myfile.bin", "wb");
    
          do
          {
              fwrite(Data->Component, sizeof(COMPONENT)-sizeof(char*), 1, pFile)
              fwrite(Data->Component.name, sizeof(char), Data->Component.nameLen, pFile)
            Data = Data->nextPtr;
          }
          while(Data !=NULL);
    
    
          fclose (pFile);
    

    【讨论】:

    • 这不起作用,因为结构中的数据项之一是动态分配的字符串指针。
    • @mbratch:这就是我写第二句话的原因。
    • 明白。我不得不要求 Op 来获取这些信息。 :)
    • 添加了一些示例和更 DRY/Lazy 的方法。
    • 我喜欢重新排列结构并将固定长度的项目作为一个块处理的想法。
    【解决方案3】:

    你应该以不同的方式编写不同的组件,检查示例:

    fwrite(Data->stringcomponent, strlen(Data->stringcomponent)+1, 1, binaryfile); // writes 1 string
    fwrite(&Data->doublecomponent, sizeof(double), 1, binaryfile); // writes 1 double
    fwrite(&Data->intcomponent, sizeof(int), 1, binaryfile); // writes 1 int
    

    所以,对于不同的数据,您将有多个 fwrite,而不是单个 fprintf,请注意不同类型的长度计算(strlen+1 或 sizeof)以及是否必须添加 &

    【讨论】:

    • 那个办法的问题是,他在阅读的时候,没有办法知道字符串的长度。
    • @CharlieBurns 对,在阅读过程中 OP 必须在文件中找到 \0 以确定字符串长度
    • 虽然您的回答在技术上没问题,但我建议您将数据转换为一定的字节顺序,甚至可能是字节数以保持便携性。
    • @glglgl 当然,这里还有很多问题(比如多字节字符串),因为我想这是家庭作业,我们可以省略一些东西
    猜你喜欢
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多