【问题标题】:how to read contents of a structure using fread() in c如何在 c 中使用 fread() 读取结构的内容
【发布时间】:2011-11-30 21:19:46
【问题描述】:

我有以下代码,我试图读取文件的内容并显示它并写入另一个文件。我的问题是我在屏幕上看到的内容与文件的内容完全不同。我已经把文件的部分内容和部分结果显示出来了

#include<iostream>
#include <stdint.h>
#include <stdio.h>
struct test
{
uint64_t start;
uint16_t length;
struct test *next;   
};

void main()
{
    char frd[32];
        std::cout<<"\nEnter name of file to read?\n";
    std::cin>>frd;
    FILE *rd=fopen(frd,"r+b");
    FILE *wrt=fopen("abc2.doc","w+");
     struct test test_st;

    while(fread (&test_st, sizeof(test_st), 1, rd))
{
       fwrite (&test_st,sizeof(test_st),1,wrt);
    printf("%llu,%u\n", test_st.start, test_st.length);
 }
fclose(rd);
fclose(wrt);
}

源文件的部分内容:

0,43 
43,95 
138,159
297,279
576,153
729,64

显示结果的前几行:

3474018176930688048,13879
3472896773804077344,14136
4049914982932231728,13362
3978707281317738034,12342
3474306356368193848,14132
3688511012684903220,14130
724298015681099573,13624

源文件和目标文件具有完全相同的副本

【问题讨论】:

    标签: c++ struct fread


    【解决方案1】:

    您的文件不包含结构,它包含逗号分隔的值(数据的文本表示)。

    结构以二进制形式存储,而不是文本形式。

    当您阅读时,您的程序会尝试将其读取的内容解释为二进制文件。撤消该操作:

    $ printf "%x%x" 3474018176930688048 13879 | sed 's/../\\\\x&/g' | sed 's/^/echo -e /e'
    061 34,067
    

    要读取以文本形式存储的数据,可以使用fgets读取每一行,然后解析它(例如:使用sscanf())。

    【讨论】:

    • 如果我必须从文件中读取结构内容,你能告诉我怎么做吗?
    • @John:首先,你需要在文件中有一个结构。
    • 文件内容包含结构对象的元素
    • 你可以用fgets()读取每一行,然后解析它(例如:使用sscanf())。
    【解决方案2】:

    这是一些工作代码。我离开了写作部分,因为我不知道你在寻找什么样的输出。只需通过阅读逻辑,您就会知道如何修复写作部分。

    我将调试 printf 留在那里,以便您了解代码是如何工作的以及如何解析 csv 文件以获得您正在寻找的结果。如上所述,该文件是文本(csv)文件而不是二进制文件。您尝试读取它的方式是读取二进制文件。所以这种方法不会有帮助。现在要读取二进制文件,您必须将它们存储为二进制文件。

    #include <iostream>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    
    struct test {
      uint64_t start;
      uint16_t length;
      struct test *next;   
    };
    
    int main(void)
    {
      char frd[32];
      std::cout<<"\nEnter name of file to read?\n";
      std::cin>>frd;
      FILE *rd=fopen(frd,"r+b");
      FILE *wrt=fopen("abc2.doc","w+");
      struct test test_st;
      char readLine[100];
    
      while(fgets(readLine, 100, rd) != NULL) {
        // Removing the new line from the end
        // This is a quick hack as Windows have two characters
        // to represent new line. It is not needed to remove newline.
        // I did so that printf output look pleasing
        readLine[strlen(readLine) - 1] = '\0';
        printf("\nr=%s", readLine);
    
        // Splitting the string based on ','
        // and then converting it to number
        char *token = NULL;
        token = strtok(readLine, ",");
        test_st.start = atol(token);
        printf("\nt1=%s, test_st.start=%llu", token, test_st.start);
    
        token = strtok(NULL, ",");
        test_st.length = atoi(token);
        printf("\nt2=%s,test_st.length=%d", token, test_st.length);
        //fwrite (&test_st,sizeof(test_st),1,wrt);
        //printf("%llu,%u\n", test_st.start, test_st.length);
      }
      fclose(rd);
      fclose(wrt);
      return 0;
    }
    

    【讨论】:

    • 这就是我要找的。谢谢一百万!
    【解决方案3】:

    写一个指向文件的指针是没有意义的。读回该指针的代码不会与编写它的代码具有相同的内存视图。所以不要那样做。

    相反,在您开始编写代码以读写二进制文件之前,请退一步。二进制文件是字节流。所以在文件中定义你想要的字节流。然后编写代码来编写您定义的确切字节流。然后编写代码以读取具有您定义的确切字节流的文件。

    那么,如果你有问题,你就会知道该怪什么。检查文件中的字节并确保它们符合定义。如果没有,那就是作者的错。如果是这样,那是读者的错。

    【讨论】:

    • 因为您的测试条件人为地简单化了。如果您将读写注释掉,您的代码仍然可以通过测试。即使您可以成功地在一个程序中写出一个指针并在另一个程序中读回它,读取程序也无法处理一个指向不再存在的地址空间中的对象的指针。
    • David 我在 c 方面没有太多的知识,如果您能用示例进行解释,将不胜感激。谢谢
    【解决方案4】:

    您也应该打开该文件以编写二进制文件:

    FILE *wrt=fopen("abc2.doc","w+b"); //instead of "w+"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-25
      • 1970-01-01
      • 2014-03-10
      • 1970-01-01
      相关资源
      最近更新 更多