【问题标题】:Read binary file using struct to find records使用结构读取二进制文件以查找记录
【发布时间】:2017-01-25 10:51:25
【问题描述】:

我正在使用以下代码来读取二进制文件并使用结构来输出数据。但是,我知道我的数据只包含一条记录,而且似乎打印出许多记录。我想知道为什么会这样?

 FILE *p;
 struct myStruct x;
 p=fopen("myfile","rb");
 //printf("Rcords of file:\n");
 while(1)
 {
     fread(&x,sizeof(x),1,p);
     if(feof(p)!=0)
         break;
        printf("\n\nID:%ld",x.ID);
    }
 fclose(p);
 return 0;

这样的结构是相当正常的:

struct myStruct
{
    int ID;     
    char name[100];
}

【问题讨论】:

  • char name; 没有意义。名称很少由单个字符组成。
  • 文件有多大? fread 返回什么?
  • 我对您的问题完全不满意,即使您进行了编辑。发minimal reproducible example,我可能已经准备好进行谈判了。
  • 您仍然可以告诉我们有关数据文件的信息:ls -la myfilewc myfile。还有fread() 的返回值是多少。如果您不检查函数的结果,您如何期望您的程序正常工作。
  • fread 是否返回1总是

标签: c struct binary fopen


【解决方案1】:

使用%d 而不是%ld 打印int

看看Why is “while ( !feof (file) )” always wrong?

struct 的大小是固定的,您可以使用ftell 获取文件的大小,然后使用struct 的大小除以获取记录数,另外,请始终检查这些函数的结果。

类似:

FILE *file;
long size;
size_t count, records;

file = fopen("myfile", "rb");
if (file == NULL) {
    perror("fopen");
    return 0;
}
if (fseek(file, 0, SEEK_END) == -1) {
    perror("fseek");
    return 0;
}
size = ftell(file);
if (size == -1) {
    perror("ftell");
    return 0;
}
if (fseek(file, 0, SEEK_SET) == -1) {
    perror("fseek");
    return 0;
}
records = size / sizeof(x);
for (count = 0; count < records; count++) {
     if (fread(&x, sizeof(x), 1, file) == 1) {
         printf("\n\nID:%d",x.ID); /* %d instead of %ld */
     } else {
         break;
     }
}

但请注意,您总是写入堆栈上的同一个变量。

编辑:

你如何在文件中存储struct

我没有存储它,一个程序是。

如果它不是你的(你没有使用相同的struct 构建文件)那么你就无法知道文件中的sizeof(x) 是哪个,请阅读结构填充和打包。

【讨论】:

  • hmmn x 是在哪里创建的?
  • hmmm 你的最小、完整和可验证的例子在哪里?这是一种避免使用几乎总是错误的feof
  • 嗯,你的版本我仍然得到多张打印。显然,我们访问这些数据的方式有问题。只有一个记录,它正在打印很多。这可能是因为它正在读取字节吗?这个例子是我能得到的最小的例子。我无法上传的文件,因为它是二进制文件
  • 如果不是你的,你怎么知道文件中结构的size
  • @user3121023,对! ftell 结果必须是 sizeof(x) 的倍数
【解决方案2】:

使用更多保护。测试函数的结果。

 FILE *p;
 struct myStruct x;
 p=fopen("myfile","rb");
 assert(p); // Insure file opened

 while(1) {
   size_t n = fread(&x, sizeof(x), 1, p);
   // feof() is insufficient, 
   // fread() can fail due to input errors too and not set end-of-file condition
   // if(feof(p)!=0)
   if (n == 0) {
     break;
   }
   // printf("\n\nID:%ld",x.ID);
   printf("\n\nID:%d", x.ID);  // Use matching specifier
   fflush(stdout); // Insure output occurs promptly
 }
 fclose(p);
 return 0;

由于 OP 的代码有一个不匹配的 printf 说明符,这表明警告未完全启用或 OP 正在使用弱编译器。建议修复它以节省时间。

【讨论】:

  • 嗨,它仍然打印出多行,而我知道 ID 只是一个值。换句话说,它不是读取结构的 ID 部分,而是读取整个结构。如何只为 ID 部分制作它?
  • @Ke。 ” 换句话说,它不是读取结构的那个 ID 部分,”与“而是整个结构”相矛盾。如果不读取归档 ID,代码将无法读取 while struct。我怀疑真实的代码和你在这里发布的不同。 2个想法:fread(&amp;x, sizeof(x), 1, p);中的x实际上是一个指针,或者您正在阅读的文件比想象的要大得多。文件大小是多少?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多