写入并关闭文件后从文件读回的问题
我想用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
超出a[x-1]
获取数据篡改时x
(< 100)记录被读取?即使100条记录被成功读取,数据是否仍会被篡改超出a[99]
? (我知道,因为尝试打印超出不当值xth
元素结果阵列a
元素的领域,如价格> 1000或价格< 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");
注意:在“文本”模式,指定块大小不起作用,因为大小取决于数据。这可能会回答你的第二个问题:由于读取的字节太少,所以最后100条记录读取已损坏。我不确定细节,但由于系统在写入/读取时添加/删除字节,因此块大小可能会有问题。
你在窗户上的机会? –
是的,我在与gcc的窗口4.9.3 – subzero
请尝试再读。你会得到25条记录吗? – Arkadiy