写入并关闭文件后从文件读回的问题

问题描述:

我想用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等数据被篡改)

+0

你在窗户上的机会? –

+0

是的,我在与gcc的窗口4.9.3 – subzero

+0

请尝试再读。你会得到25条记录吗? – Arkadiy

你不应该开文本模式下的文件,而读/写为二进制结构。

尽管它对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条记录读取已损坏。我不确定细节,但由于系统在写入/读取时添加/删除字节,因此块大小可能会有问题。

+0

尽管这样做有效,但我不会在文件的任何位置输入任何行,所以您确定此转换是问题吗?另外,当我以“w +”模式打开它,并且不关闭它并重新打开而只是倒带然后阅读时,它似乎工作正常!那么关闭它并重新打开它意味着一些问题?就像在文件中标记eof或类似的问题一样? – subzero

+0

你是在写保管箱吗? –

+0

如果您指的是文件托管服务收件箱,那么不需要! – subzero