2017-02-14 60 views
1

我想用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

回答

1

你不應該開文本模式下的文件,而讀/寫爲二進制結構。

儘管它對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