我正在尝试使用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
ferror:0
问题1 :为什么eof在写入超过25个时只读取了25条记录? (我在重新打开文件后尝试使用rewind
/ fseek
,但问题仍然存在。)
问题2 :在这种情况下,a
(&lt; 1)}之后,a[x-1]
以外的数组x
中包含的数据被篡改是否正常? 100)记录被读取?即使成功读取了100条记录,数据是否仍会被篡改超过a[99]
? (我知道数据被篡改,因为尝试打印a
元素之外的数组xth
元素的字段会导致不合适的值,例如价格&gt; 1000或价格&lt; 0等等)
答案 0 :(得分:1)
在读取/写入二进制结构时,您不应该以文本模式打开文件。
虽然它对Linux / Unix没有影响,但在Windows上会产生严重后果。它使您的文件在Windows和Linux之间不可共享。
取决于数据LF&lt; =&gt; 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");
注意:&#34; text&#34;模式,指定块大小不起作用,因为大小取决于数据。这可能回答了你的第二个问题:最后100条记录读取已损坏,因为你读的字节太少了。我不确定细节,但由于系统在写/读时添加/删除字节,因此块大小可能有问题。