如何在c中使用fread()读取结构的内容

时间:2011-11-30 21:19:46

标签: c++ struct fread

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

#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

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

4 个答案:

答案 0 :(得分:2)

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

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

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

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

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

我将调试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 :(得分:0)

你也应该打开文件来写二进制文件:

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