gpt4 book ai didi

c - 在写入文件并在 c 中关闭文件后从文件中读回的问题

转载 作者:太空宇宙 更新时间:2023-11-04 03:24:37 26 4
gpt4 key购买 nike

我正在尝试使用 fread 和 fwrite 来读取和写入与文件中的结构有关的数据。这是我的代码:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>

typedef struct book book;

struct book
{
char title[200];
char auth[200];
char publi[200];
int p_year;
int price;
int edition;
int isbn;
};

int main()
{
int i;
FILE* fp = fopen("this.dat","w");
book * a = calloc(1000000,sizeof (book));

srand(time(NULL));

for(i=0;i<1000000;i++)
{
a[i].price = rand()%1000;
a[i].p_year = 1500 + rand()%518;
a[i].isbn = 10000+rand()%100000;
a[i].edition = i%15;

strcpy(a[i].title,"title");
strcpy(a[i].auth,"author");
strcpy(a[i].publi,"publication");
}

if((i=fwrite(a,sizeof(*a),1000000,fp))!= 1000000)
{
printf("ERROR - Only %d records written\n",i);
printf("feof:%d\nferror:%d",feof(fp),ferror(fp));
return EXIT_FAILURE;
}

if(ferror(fp))
{
printf("ERROR");
return EXIT_FAILURE;
}

if(fclose(fp)!=0)
{
printf("ERROR while closing the stream");
return EXIT_FAILURE;
}

if((fp = fopen("this.dat","r")) == NULL)
{
printf("ERROR reopening");
return EXIT_FAILURE;
}

if((i=fread(a,sizeof(book),100,fp))!=100)
{
printf("ERROR - Only %d records read\n",i);
printf("feof:%d\nferror:%d",feof(fp),ferror(fp));
return EXIT_FAILURE;
}

if(ferror(fp))
{
printf("~ERROR");
return EXIT_FAILURE;
}

for(i=0;i<100;i++)
printf("price:%d\nedition:%d\nisbn:%d\np_year:%d\n\n\n",a[i].price,a[i].edition,a[i].isbn,a[i].p_year);


fclose(fp);
return EXIT_SUCCESS;
}

问题是它偶尔会成功执行,但大多数时候不会。使用 fread 从文件中读回时出现错误。它最终每次读取可变数量的记录并且记录数量少于预期(即 100)。以下是程序执行失败的输出之一:

错误 - 仅读取了 25 条记录
feof:16
错误:0

问题一:为什么写了25条以上的记录,eof只读取了25条记录? (我尝试在重新打开文件后使用 rewind/fseek,但问题仍然存在。)

问题2:在这种情况下,a[x-1]数组a中包含的数据超出a[x-1]是否正常在读取 x (<100) 条记录时被篡改?即使成功读取了 100 条记录,数据是否仍然被篡改超过 a[99](我知道数据被篡改了,因为尝试打印超出 xth 元素的数组 a 元素的字段会导致不适当的值,例如 price > 1000 或 price <0 等等)

最佳答案

在以二进制结构读取/写入文件时,不应以文本模式打开文件。

虽然它对 Linux/Unix 没有影响,但在 Windows 上会产生严重后果。它使您的文件无法在 Windows 和 Linux 之间共享。

根据数据 LF <=> CR/LF 转换可以破坏/移动数据(删除回车或插入一个)

在 Windows 的文本模式下,每个 LF (ASCII 10) 字节在写入时被 CR+LF (13+10 ASCII) 字节替换(在读取时相反:13+10 => 10)。这 10 个字节可能会发生,例如将 1802 年(十六进制:0x70A)写入二进制时。

解决方案:使用二进制模式:

if((fp = fopen("this.dat","rb")) == NULL)

FILE* fp = fopen("this.dat","wb");

注意:在“文本”模式下,指定 block 大小不起作用,因为大小取决于数据。这可能回答了您的第二个问题:最后读取的第 100 条记录已损坏,因为您读取的字节太少。我不确定细节,但由于系统在写入/读取时添加/删除字节, block 大小可能有问题。

关于c - 在写入文件并在 c 中关闭文件后从文件中读回的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42232644/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com