




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第八章
文件第八章
文件C文件概述文件類型指針文件的打開和關閉文件的讀寫文件的定位出錯的檢測文件的輸入輸出小結C文件概述(一)C文件概述(一)C文件概述C文件概述文件(file)是程序設計中一個重要的概念。所謂“文件”一般指存儲在外部介質上數據的集合。一批數據是以文件的形式存放在外部介質(如磁盤)上的。操作系統是以文件為單位對數據進行管理的,也就是說,如果想找存在外部介質上的數據,必須先按文件名找到所指定的文件,然后再從該文件中讀取數據。要向外部介質上存儲數據也必須先建立一個文件(以文件名標識),才能向它輸出數據。以前各章中所用到的輸入和輸出,都是以終端為對象的,即從終端鍵盤輸入數據,運行結果輸出到終端上。從操作系統的角度看,每一個與主機相聯的輸入輸出設備都看作是一個文件。例如,終端鍵盤是輸入文件,顯示屏和打印機是輸出文件。C文件概述文件(file)是程序設計中一個重要的概念。C文件概述在程序運行時,常常需要將一些數據(運行的最終結果或中間數據)輸出到磁盤上存放起來,以后需要時再從磁盤中輸入到計算機內存。這就要用到磁盤文件。C語言把文件看作是一個字符(字節)的序列,即由一個一個字符(字節)的數據順序組成。根據數據的組織形式,可分為ASCII文件和二進制文件。ASCII文件又稱文本(text)文件,它的每一個字節放一個ASCII代碼,代表一個字符。二進制文件是把內存中的數據按其在內存中的存儲形式原樣輸出到磁盤上存放。如果有一個整數10000,在內存中占4個字節,如果按ASCII碼形式輸出,則占5個字節,而按二進制形式輸出,在磁盤上只占4個字節。用ASCII碼形式輸出與字符一一對應,一個字節代表一個字符,一個字節代表一個字符,因而便于對字符進行逐個處理,也便于輸出字符。但一般占存儲空間較多,而且要花費轉換時間(二進制形式與ASCII碼間的轉換)。用二進制形式輸出數值,可以節省外存空間和轉換時間,但一個字節并不對應一個字符,不能直接輸出字符形式。一般中間結果數據需要暫時保存在外存上以后又需要輸入到內存的,常用二進制文件保存。C文件概述在程序運行時,常常需要將一些數據(運行的最終結果或C文件概述由前所述,一個C文件是一個字節流或二進制流。它把數據看作是一連串的字符(字節),而不考慮記錄的界限。換句話說,C語言中文件并不是由記錄(record)組成的。在C語言中對文件的存取是以字符(字節)為單位的。輸入輸出的數據流的開始和結束僅受程序控制而不受物理符號(如回車換行符)控制。也就是說,在輸出時不會自動增加回車換行符以作為記錄結束的標志,輸入時不以回車換行符作為記錄的間隔(事實上C文件并不由記錄構成)。我們把這種文件稱為流式文件。C語言允許對文件存取一個字符,這就增加了處理的靈活性。在C語言中,沒有輸入輸出語句,對文件的讀寫都是用庫函數來實現的。ANSI規定了標準輸入輸出函數,用它們對文件進行讀寫。C文件概述由前所述,一個C文件是一個字節流或二進制流。它把數C文件概述有兩種對文件的處理方法:一種叫“緩沖文件系統”;一種叫“非緩沖文件系統”。所謂緩沖文件系統是指系統自動地在內存區為每一個正在使用的文件名開辟一個緩沖區。從內存向磁盤輸出數據必須先送到內存中的緩沖區,裝滿緩沖區后才一起送到磁盤去。如果從磁盤向內存讀入數據,則一次從磁盤文件將一批數據輸入到內存緩沖區(充滿緩沖區),然后再從緩沖區逐個地將數據送到程序數據區(給程序變量)。如下圖所示。緩沖區的大小由各個具體的C版本確定,一般為512字節。C文件概述有兩種對文件的處理方法:C語言第9章-文件教學課件C文件概述所謂“非緩沖文件系統”是指系統不自動開辟確定大小的緩沖區,而由程序為每個文件設定緩沖區。在UNIX系統下,用緩沖文件系統來處理文本文件,用非緩沖文件系統處理二進制文件。用緩沖文件系統進行的輸入輸出又稱為高級(或高層)磁盤輸入輸出(高層I/O)。用非緩沖文件系統進行的輸入輸出又稱為低級(低層)輸入輸出系統。ANSIC標準決定不采用非緩沖文件系統,而只采用緩沖文件系統。即既用緩沖文件系統處理文本文件,也用它來處理二進制文件。也就是將緩沖文件系統擴充為可以處理二進制文件。本章只介紹ANSIC規定的文件系統以及對它的讀寫。C文件概述所謂“非緩沖文件系統”是指系統不自動開辟確定大小的(二)文件類型指針(二)文件類型指針文件類型指針緩沖文件系統中,關鍵的概念是“文件指針”。每個被使用的文件都在內存中開辟一個區,用來存放文件的有關信息(如文件的名字、文件狀態及文件當前位置等)。這些信息是保存在一個結構體變量中的。該結構體類型是由系統定義的,取名為FILE。TurboC在stdio.h文件中有以下的文件類型聲明:文件類型指針緩沖文件系統中,關鍵的概念是“文件指針”。每個被typedefstruct{ shortlevel;/*緩沖區“滿”或“空”的程度*/ unsignedflags;/*文件狀態標志*/ charfd;/*文件描述符*/ unsignedcharhold;/*如無緩沖區不讀取字符*/ shortbsize;/*緩沖區的大小*/ unsignedchar*baffer;/*數據緩沖區的位置*/ unsignedar*curp;/*指針,當前的指向*/ unsignedistemp;/*臨時文件,指示器*/ shorttoken;/*用于有效性檢查*/}FILE;typedefstruct文件類型指針可以定義文件型指針變量。如: FILEfp;如果有n個文件,一般應設n個指針變量(指向FILE類型結構體的指針變量),使它們分別指向n個文件(確切地說指向存放該文件信息的結構體變量),以實現對文件的訪問。文件類型指針可以定義文件型指針變量。如:(三)文件的打開與關閉(三)文件的打開與關閉文件打開fopen函數對文件讀寫之前應該“打開”該文件,在使用結束之后應關閉該文件。ANSIC規定了標準輸入輸出函數庫,用fopen()函數來實現打開文件。fopen函數的調用方式通常為 FILE*fp; fp=fopen(文件名,使用文件方式);例如: fp=fopen("a1","r");可以看出,在打開一個文件時,通知給編譯系統以下3個信息:
①需要打開的文件名,也就是準備訪問的文件的名字。②使用文件的方式(“讀”還是“寫”等)。③讓哪一個指針變量指向被打開的文件。文件打開fopen函數對文件讀寫之前應該“打開”該文件,在使文件打開fopen函數文件使用方式參見書上P333表13-1。說明:1)用“r”方式:只讀方式,打開的文件只能用于向計算機輸入而不能用作向該文件輸出數據,而且該文件應該已經存在,不能用“r”方式打開一個并不存在的文件(即輸入文件),否則出錯。2)用“w”方式:只寫方式,打開的文件只能用于向該文件寫數據(即輸出文件),而不能用來向計算機輸入。如果原來不存在該文件,則在打開時新建立一個以指定的名字命名的文件。如果原來已存在一個以該文件名命名的文件,則在打開時將該文件刪去,然后重新建立一個新文件。文件打開fopen函數文件使用方式參見書上P333表13-1文件打開fopen函數3)如果希望向文件末尾添加新的數據(不希望刪除原有數據),則應該用“a”方式打開。但此時該文件必須已存在,否則將得到出錯信息。打開時,位置指針移到文件末尾。4)用“r+”、“w+”、“a+”方式打開的文件既可以用來輸入數據,也可以用來輸出數據。用“r+”方式時該文件應該已經存在,以便能向計算機輸入數據。用“w+”方式則新建立一個文件,先向此文件寫數據,然后可以讀此文件中的數據。用“a+”方式打開的文件,原來的文件不被刪去,位置指針移到文件末尾,可以添加,也可以讀。文件打開fopen函數3)如果希望向文件末尾添加新的數據(不文件打開fopen函數5)如果不能實現“打開”的任務,fopen函數將會帶回一個出錯信息。出錯的原因可能是用“r”方式打開一個并不存在的文件;磁盤出故障;磁盤已滿無法建立新文件等。此時fopen函數將帶回一個空指針值NULL(NULL在stdio.h文件中已被定義為0)。常用下面的方法打開一個文件: if((fp=fopen("file1","r"))==NULL) { printf("cannotopenthisfile\n"); …… }即先檢查打開的操作有否出錯,如果有錯就在終端上輸出“cannotopenthisfile”。文件打開fopen函數5)如果不能實現“打開”的任務,fop文件打開fopen函數6)用以上方式可以打開文本文件或二進制文件,這是ANSIC的規定,用同一種緩沖文件系統來處理文本文件和二進制文件。但目前使用的有些C編譯系統可能不完全提供所有這些功能(例如有的只能用“r”、“w”、“a”方式),有的C版本不用“r+”、“w+”、“a+”,而用“rw”、“wr”、“ar”等,請讀者注意所用系統的規定。(7)在向計算機輸入文本文件時,將回車換行符轉換為一個換行符,在輸出時把換行符轉換成為回車和換行兩個字符。在用二進制文件時,不進行這種轉換,在內存中的數據形式與輸出到外部文件中的數據形式完全一致,一一對應。文件打開fopen函數6)用以上方式可以打開文本文件或二進制文件打開fopen函數8)在程序開始運行時,系統自動打開3個標準文件:標準輸入、標準輸出、標準出錯輸出。通常這3個文件都與終端相聯系。因此以前我們所用到的從終端輸入或輸出都不需要打開終端文件。系統自動定義了3個文件指針stdin、stdout和stderr,分別指向終端輸入、終端輸出和標準出錯輸?也從終端輸出)。如果程序中指定要從stdin所指的文件輸入數據,就是指從終端鍵盤輸入數據。文件打開fopen函數8)在程序開始運行時,系統自動打開3個文件關閉fclose函數在使用完一個文件后應該關閉它,以防止它再被誤用。“關閉”就是使文件指針變量不指向該文件,也就是文件指針變量與文件“脫鉤”,此后不能再通過該指針對原來與其相聯系的文件進行讀寫操作。除非再次打開,使該指針變量重新指向該文件。用fclose函數關閉文件。fclose函數調用的一般形式為 fclose(文件指針);例如: fclose(fp);fclose函數也帶回一個值,當順利地執行了關閉操作,則返回值為0;否則返回EOF(-1)。文件關閉fclose函數在使用完一個文件后應該關閉它,以防止文件關閉fclose函數應該養成在程序終止之前關閉所有文件的習慣,如果不關閉文件將會丟失數據。因為,如前所述,在向文件寫數據時,是先將數據輸到緩沖區,待緩沖區充滿后才正式輸出給文件。如果當數據未充滿緩沖區而程序結束運行,就會將緩沖區中的數據丟失。用fclose函數關閉文件,可以避免這個問題,它先把緩沖區中的數據輸出到磁盤文件,然后才釋放文件指針變量。文件關閉fclose函數應該養成在程序終止之前關閉所有文件的(四)文件的讀寫(四)文件的讀寫fputc寫文件函數把一個字符寫到磁盤文件上去。其一般調用形式為: fputc(ch,fp);其中:ch是要輸出的字符,它可以是一個字符常量,也可以是一個字符變量。fp是文件指針變量。fputc(ch,fp)函數的作用是將字符(ch的值)輸出到fp所指向的文件中去。fputc函數也帶回一個值:如果輸出成功則返回值就是輸出的字符;如果輸出失敗,則返回一個EOF(-1)。EOF是在stdio.h文件中定義的符號常量,值為-1。fputc寫文件函數把一個字符寫到磁盤文件上去。其一般調用形fputc寫文件函數在前面介紹過putchar函數,其實putchar是從fputc函數派生出來的。putchar(c)是在stdio.h文件中用預處理命令#define定義的宏:#defineputchar(c)fputc(c,stdout)前面已敘述,stdout是系統定義的文件指針變量,它與終端輸出相連。fputc(c,stdout)的作用是將c的值輸出到終端。用宏putchar(c)比寫fputc(c,stdout)簡單一些。從用戶的角度,可以把putchar(c)看作函數而不必嚴格地稱它為宏。fputc寫文件函數在前面介紹過putchar函數,其實pufgetc讀文件函數從指定的文件讀入一個字符,該文件必須是以讀或讀寫方式打開的。fgetc函數的調用形式為 ch=fgetc(fp);fp為文件型指針變量,ch為字符變量。fgetc函數帶回一個字符,賦給ch。如果在執行fgetc函數讀字符時遇到文件結束符,函數返回一個文件結束標志EOF(-1)。如果想從一個磁盤文件順序讀入字符并在屏幕上顯示出來,可以: ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp);}fgetc讀文件函數從指定的文件讀入一個字符,該文件必須是以feof()判斷文件是否結束函數注意:EOF不是可輸出字符,因此不能在屏幕上顯示。由于字符的ASCII碼不可能出現-1,因此EOF定義為-1是合適的。當讀入的字符值等于-1(即EOF)時,表示讀入的已不是正常的字符而是文件結束符。但以上只適用于讀文本文件的情況?,F在ANSIC已允許用緩沖文件系統處理二進制文件,而讀入某一個字節中的二進制數據的值有可能是-1,而這又恰好是EOF的值。這就出現了需要讀入有用數據而卻被處理為“文件結束”的情況。為了解決這個問題,ANSIC提供一個feof函數來判斷文件是否真的結束。 feof(fp)用來測試fp所指向的文件當前狀態是否“文件結束”。如果是文件結束,函數feof(fp)的值為1(真),否則為0(假)。feof()判斷文件是否結束函數注意:EOF不是可輸出字符,feof()判斷文件是否結束函數如: while(!feof(fp)) { c=fgetc(fp); …}feof()判斷文件是否結束函數如:fputc和fgetc舉例例12.1從鍵盤輸入一些字符,逐個把它們送到磁盤上去,直到輸入一個“#”為止。源碼參見12-1.c例12.2將一個磁盤文件中的信息復制到另一個磁盤文件中。源碼參見12-2\a.c使用命令行方式輸入兩個文件名;源碼參見12-2\b.cfputc和fgetc舉例例12.1從鍵盤輸入一些字符,逐fread和fwrite函數ANSIC標準提出設置兩個函數(fread和fwrite),用來讀寫一個數據塊。它們的一般調用形式為 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp);其中:buffer:是一個指針。對fread來說,它是讀入數據的存放地址。對fwrite來說,是要輸出數據的地址(以上指的是起始地址)。size:要讀寫的字節數。count:要進行讀寫多少個size字節的數據項。fp:文件型指針。如果fread或fwrite調用成功,則函數返回值為count的值,即輸入或輸出數據項的完整個數。fread和fwrite函數ANSIC標準提出設置兩個函數fread和fwrite函數如果文件以二進制形式打開,用fread和fwrite函數就可以讀寫任何類型的信息,如: fread(f,4,2,fp);其中f是一個實型數組名。一個實型變量占4個字節。這個函數從fp所指向的文件讀入2次(每次4個字節)數據,存儲到數組f中。fread和fwrite函數如果文件以二進制形式打開,用frfread和fwrite函數如果有一個如下的結構體類型: structstudent-type { charname[10]; intnum; intage; charaddr[30]; }stud[40];假設學生的數據已存放在磁盤文件中,可以用下面的for語句和fread函數讀入40個學生的數據: for(i=0;i<40;i++) { fread(&stud[i],sizeof(structstudent-type),1,fp); }同樣,以下for語句和fwrite函數可以將內存中的學生數據輸出到磁盤文件中去: for(i=0;i<40,i++) { fwrite(&stud[i],sizeof(structstudent-type),1,fp); }fread和fwrite函數如果有一個如下的結構體類型:fread和fwrite函數舉例例12.3從鍵盤輸入4個學生的有關數據,然后把它們轉存到磁盤文件上去。源碼參見12-3fread和fwrite函數舉例例12.3從鍵盤輸入4個學其它讀寫函數自學。其它讀寫函數自學。(五)文件的定位(五)文件的定位文件中有一個位置指針,指向當前讀寫的位置。如果順序讀寫一個文件,每次讀寫一個字符,則讀寫完一個字符后,該位置指針自動移動指向下一個字符位置。如果想改變這樣的規律,強制使位置指針指向其他指定的位置,可以用有關函數。文件中有一個位置指針,指向當前讀寫的位置。如果順序讀寫一個文rewind函數rewind函數的作用是使位置指針重新返回文件的開頭。此函數沒有返回值。例12.4有一個磁盤文件,第一次將它的內容顯示在屏幕上,第二次把它復制到另一文件上。源碼參見12-4.crewind函數rewind函數的作用是使位置指針重新返回文fseek函數和隨機讀寫對流式文件可以進行順序讀寫,也可以進行隨機讀寫。關鍵在于控制文件的位置指針,如果位置指針是按字節位置順序移動的,就是順序讀寫。如果能將位置指針按需要移動到任意位置,就可以實現隨機讀寫。所謂隨機讀寫,是指讀寫完上一個字符(字節)后,并不一定要讀寫其后續的字符(字節),而可以讀寫文件中任意所需的字符(字節)。用fseek函數可以實現改變文件的位置指針。fseek函數和隨機讀寫對流式文件可以進行順序讀寫,也可以進fseek函數和隨機讀寫fseek函數的調用形式為: fseek(文件類型指針,位移量,起始點)其中:“起始點”用0、1或2代替,0代表“文件開始”,1為“當前位置”,2為“文件末尾”。ANSIC標準指定的名字如表13.2所示(見書上P345)?!拔灰屏俊敝敢浴捌鹗键c”為基點,向前移動的字節數。ANSIC和大多數C版本要求位移量是long型數據。這樣當文件的長度大于64K時不致出問題。ANSIC標準規定在數字的末尾加一個字母L,就表示是long型。下面是fseek函數調用的幾個例子:fseek(fp,100L,0);將位置指針移到離文件頭100個字節處fseek(fp,50L,1);將位置指針移到離當前位置50個字節處fseek(fp,-10L,2);將位置指針從文件末尾處向后退10個字節fseek函數和隨機讀寫fseek函數的調用形式為:fseek示例例12.5在磁盤文件上存有10個學生的數據。要求將第1、3、5、7、9個學生數據輸入計算機,并在屏幕上顯示出來。源代碼參見12-5.cfseek示例例12.5在磁盤文件上存有10個學生的數據。ftell函數ftell函數的作用是得到流式文件中的當前位置,用相對于文件開頭的位移量來表示。由于文件中的位置指針經常移動,人們往往不容易知道其當前位置。用ftell函數可以得到當前位置。如果ftell函數返回值為-1L,表示出錯。例如: i=ftell(fp); if(i==-1L) { printf("error\n"); }ftell函數ftell函數的作用是得到流式文件中的當前位置(六)出錯的檢測(六)出錯的檢測ferror函數在調用各種輸入輸出函數(如putc、getc、fread、fwrite等)時,如果出現錯誤,除了函數返回值有所反映外,還可以用ferror函數檢查。它的一般調用形式為: ferror(fp);如果ferror返回值為0(假),表示未出錯。如果返回一個非零值,表示出錯。應該注意,對同一個文件每一次調用輸入輸出函數,均產生一個新的ferror函數值,因此,應當在調用一個輸入輸出函數后立即檢查ferror函數的值,否則信息會丟失。在執行fopen函數時,ferror函數的初始值自動置為0。ferror函數在調用各種輸入輸出函數(如putc、getcclearerr函數它的作用是使文件錯誤標志和文件結束標志置為0。假設在調用一個輸入輸出函數時出現錯誤,ferror函數值為一個非零值。在調用clearerr(fp)后,ferror(fp)的值變成0。只要出現錯誤標志,就一直保留,直到對同一文件調用clearerr函數或rewind函數,或任何其他一個輸入輸出函數。clearerr函數它的作用是使文件錯誤標志和文件結束標志置(七)文件輸入輸出小結(七)文件輸入輸出小結文件使用可以參考表12-3(書P307)和表12-1(書P293);在實際需要時,可以查閱這兩個表。當然,這兩個表列出的內容只是常用的函數和標志。文件使用可以參考表12-3(書P307)和表12-1(書P2第八章
文件第八章
文件C文件概述文件類型指針文件的打開和關閉文件的讀寫文件的定位出錯的檢測文件的輸入輸出小結C文件概述(一)C文件概述(一)C文件概述C文件概述文件(file)是程序設計中一個重要的概念。所謂“文件”一般指存儲在外部介質上數據的集合。一批數據是以文件的形式存放在外部介質(如磁盤)上的。操作系統是以文件為單位對數據進行管理的,也就是說,如果想找存在外部介質上的數據,必須先按文件名找到所指定的文件,然后再從該文件中讀取數據。要向外部介質上存儲數據也必須先建立一個文件(以文件名標識),才能向它輸出數據。以前各章中所用到的輸入和輸出,都是以終端為對象的,即從終端鍵盤輸入數據,運行結果輸出到終端上。從操作系統的角度看,每一個與主機相聯的輸入輸出設備都看作是一個文件。例如,終端鍵盤是輸入文件,顯示屏和打印機是輸出文件。C文件概述文件(file)是程序設計中一個重要的概念。C文件概述在程序運行時,常常需要將一些數據(運行的最終結果或中間數據)輸出到磁盤上存放起來,以后需要時再從磁盤中輸入到計算機內存。這就要用到磁盤文件。C語言把文件看作是一個字符(字節)的序列,即由一個一個字符(字節)的數據順序組成。根據數據的組織形式,可分為ASCII文件和二進制文件。ASCII文件又稱文本(text)文件,它的每一個字節放一個ASCII代碼,代表一個字符。二進制文件是把內存中的數據按其在內存中的存儲形式原樣輸出到磁盤上存放。如果有一個整數10000,在內存中占4個字節,如果按ASCII碼形式輸出,則占5個字節,而按二進制形式輸出,在磁盤上只占4個字節。用ASCII碼形式輸出與字符一一對應,一個字節代表一個字符,一個字節代表一個字符,因而便于對字符進行逐個處理,也便于輸出字符。但一般占存儲空間較多,而且要花費轉換時間(二進制形式與ASCII碼間的轉換)。用二進制形式輸出數值,可以節省外存空間和轉換時間,但一個字節并不對應一個字符,不能直接輸出字符形式。一般中間結果數據需要暫時保存在外存上以后又需要輸入到內存的,常用二進制文件保存。C文件概述在程序運行時,常常需要將一些數據(運行的最終結果或C文件概述由前所述,一個C文件是一個字節流或二進制流。它把數據看作是一連串的字符(字節),而不考慮記錄的界限。換句話說,C語言中文件并不是由記錄(record)組成的。在C語言中對文件的存取是以字符(字節)為單位的。輸入輸出的數據流的開始和結束僅受程序控制而不受物理符號(如回車換行符)控制。也就是說,在輸出時不會自動增加回車換行符以作為記錄結束的標志,輸入時不以回車換行符作為記錄的間隔(事實上C文件并不由記錄構成)。我們把這種文件稱為流式文件。C語言允許對文件存取一個字符,這就增加了處理的靈活性。在C語言中,沒有輸入輸出語句,對文件的讀寫都是用庫函數來實現的。ANSI規定了標準輸入輸出函數,用它們對文件進行讀寫。C文件概述由前所述,一個C文件是一個字節流或二進制流。它把數C文件概述有兩種對文件的處理方法:一種叫“緩沖文件系統”;一種叫“非緩沖文件系統”。所謂緩沖文件系統是指系統自動地在內存區為每一個正在使用的文件名開辟一個緩沖區。從內存向磁盤輸出數據必須先送到內存中的緩沖區,裝滿緩沖區后才一起送到磁盤去。如果從磁盤向內存讀入數據,則一次從磁盤文件將一批數據輸入到內存緩沖區(充滿緩沖區),然后再從緩沖區逐個地將數據送到程序數據區(給程序變量)。如下圖所示。緩沖區的大小由各個具體的C版本確定,一般為512字節。C文件概述有兩種對文件的處理方法:C語言第9章-文件教學課件C文件概述所謂“非緩沖文件系統”是指系統不自動開辟確定大小的緩沖區,而由程序為每個文件設定緩沖區。在UNIX系統下,用緩沖文件系統來處理文本文件,用非緩沖文件系統處理二進制文件。用緩沖文件系統進行的輸入輸出又稱為高級(或高層)磁盤輸入輸出(高層I/O)。用非緩沖文件系統進行的輸入輸出又稱為低級(低層)輸入輸出系統。ANSIC標準決定不采用非緩沖文件系統,而只采用緩沖文件系統。即既用緩沖文件系統處理文本文件,也用它來處理二進制文件。也就是將緩沖文件系統擴充為可以處理二進制文件。本章只介紹ANSIC規定的文件系統以及對它的讀寫。C文件概述所謂“非緩沖文件系統”是指系統不自動開辟確定大小的(二)文件類型指針(二)文件類型指針文件類型指針緩沖文件系統中,關鍵的概念是“文件指針”。每個被使用的文件都在內存中開辟一個區,用來存放文件的有關信息(如文件的名字、文件狀態及文件當前位置等)。這些信息是保存在一個結構體變量中的。該結構體類型是由系統定義的,取名為FILE。TurboC在stdio.h文件中有以下的文件類型聲明:文件類型指針緩沖文件系統中,關鍵的概念是“文件指針”。每個被typedefstruct{ shortlevel;/*緩沖區“滿”或“空”的程度*/ unsignedflags;/*文件狀態標志*/ charfd;/*文件描述符*/ unsignedcharhold;/*如無緩沖區不讀取字符*/ shortbsize;/*緩沖區的大小*/ unsignedchar*baffer;/*數據緩沖區的位置*/ unsignedar*curp;/*指針,當前的指向*/ unsignedistemp;/*臨時文件,指示器*/ shorttoken;/*用于有效性檢查*/}FILE;typedefstruct文件類型指針可以定義文件型指針變量。如: FILEfp;如果有n個文件,一般應設n個指針變量(指向FILE類型結構體的指針變量),使它們分別指向n個文件(確切地說指向存放該文件信息的結構體變量),以實現對文件的訪問。文件類型指針可以定義文件型指針變量。如:(三)文件的打開與關閉(三)文件的打開與關閉文件打開fopen函數對文件讀寫之前應該“打開”該文件,在使用結束之后應關閉該文件。ANSIC規定了標準輸入輸出函數庫,用fopen()函數來實現打開文件。fopen函數的調用方式通常為 FILE*fp; fp=fopen(文件名,使用文件方式);例如: fp=fopen("a1","r");可以看出,在打開一個文件時,通知給編譯系統以下3個信息:
①需要打開的文件名,也就是準備訪問的文件的名字。②使用文件的方式(“讀”還是“寫”等)。③讓哪一個指針變量指向被打開的文件。文件打開fopen函數對文件讀寫之前應該“打開”該文件,在使文件打開fopen函數文件使用方式參見書上P333表13-1。說明:1)用“r”方式:只讀方式,打開的文件只能用于向計算機輸入而不能用作向該文件輸出數據,而且該文件應該已經存在,不能用“r”方式打開一個并不存在的文件(即輸入文件),否則出錯。2)用“w”方式:只寫方式,打開的文件只能用于向該文件寫數據(即輸出文件),而不能用來向計算機輸入。如果原來不存在該文件,則在打開時新建立一個以指定的名字命名的文件。如果原來已存在一個以該文件名命名的文件,則在打開時將該文件刪去,然后重新建立一個新文件。文件打開fopen函數文件使用方式參見書上P333表13-1文件打開fopen函數3)如果希望向文件末尾添加新的數據(不希望刪除原有數據),則應該用“a”方式打開。但此時該文件必須已存在,否則將得到出錯信息。打開時,位置指針移到文件末尾。4)用“r+”、“w+”、“a+”方式打開的文件既可以用來輸入數據,也可以用來輸出數據。用“r+”方式時該文件應該已經存在,以便能向計算機輸入數據。用“w+”方式則新建立一個文件,先向此文件寫數據,然后可以讀此文件中的數據。用“a+”方式打開的文件,原來的文件不被刪去,位置指針移到文件末尾,可以添加,也可以讀。文件打開fopen函數3)如果希望向文件末尾添加新的數據(不文件打開fopen函數5)如果不能實現“打開”的任務,fopen函數將會帶回一個出錯信息。出錯的原因可能是用“r”方式打開一個并不存在的文件;磁盤出故障;磁盤已滿無法建立新文件等。此時fopen函數將帶回一個空指針值NULL(NULL在stdio.h文件中已被定義為0)。常用下面的方法打開一個文件: if((fp=fopen("file1","r"))==NULL) { printf("cannotopenthisfile\n"); …… }即先檢查打開的操作有否出錯,如果有錯就在終端上輸出“cannotopenthisfile”。文件打開fopen函數5)如果不能實現“打開”的任務,fop文件打開fopen函數6)用以上方式可以打開文本文件或二進制文件,這是ANSIC的規定,用同一種緩沖文件系統來處理文本文件和二進制文件。但目前使用的有些C編譯系統可能不完全提供所有這些功能(例如有的只能用“r”、“w”、“a”方式),有的C版本不用“r+”、“w+”、“a+”,而用“rw”、“wr”、“ar”等,請讀者注意所用系統的規定。(7)在向計算機輸入文本文件時,將回車換行符轉換為一個換行符,在輸出時把換行符轉換成為回車和換行兩個字符。在用二進制文件時,不進行這種轉換,在內存中的數據形式與輸出到外部文件中的數據形式完全一致,一一對應。文件打開fopen函數6)用以上方式可以打開文本文件或二進制文件打開fopen函數8)在程序開始運行時,系統自動打開3個標準文件:標準輸入、標準輸出、標準出錯輸出。通常這3個文件都與終端相聯系。因此以前我們所用到的從終端輸入或輸出都不需要打開終端文件。系統自動定義了3個文件指針stdin、stdout和stderr,分別指向終端輸入、終端輸出和標準出錯輸?也從終端輸出)。如果程序中指定要從stdin所指的文件輸入數據,就是指從終端鍵盤輸入數據。文件打開fopen函數8)在程序開始運行時,系統自動打開3個文件關閉fclose函數在使用完一個文件后應該關閉它,以防止它再被誤用?!瓣P閉”就是使文件指針變量不指向該文件,也就是文件指針變量與文件“脫鉤”,此后不能再通過該指針對原來與其相聯系的文件進行讀寫操作。除非再次打開,使該指針變量重新指向該文件。用fclose函數關閉文件。fclose函數調用的一般形式為 fclose(文件指針);例如: fclose(fp);fclose函數也帶回一個值,當順利地執行了關閉操作,則返回值為0;否則返回EOF(-1)。文件關閉fclose函數在使用完一個文件后應該關閉它,以防止文件關閉fclose函數應該養成在程序終止之前關閉所有文件的習慣,如果不關閉文件將會丟失數據。因為,如前所述,在向文件寫數據時,是先將數據輸到緩沖區,待緩沖區充滿后才正式輸出給文件。如果當數據未充滿緩沖區而程序結束運行,就會將緩沖區中的數據丟失。用fclose函數關閉文件,可以避免這個問題,它先把緩沖區中的數據輸出到磁盤文件,然后才釋放文件指針變量。文件關閉fclose函數應該養成在程序終止之前關閉所有文件的(四)文件的讀寫(四)文件的讀寫fputc寫文件函數把一個字符寫到磁盤文件上去。其一般調用形式為: fputc(ch,fp);其中:ch是要輸出的字符,它可以是一個字符常量,也可以是一個字符變量。fp是文件指針變量。fputc(ch,fp)函數的作用是將字符(ch的值)輸出到fp所指向的文件中去。fputc函數也帶回一個值:如果輸出成功則返回值就是輸出的字符;如果輸出失敗,則返回一個EOF(-1)。EOF是在stdio.h文件中定義的符號常量,值為-1。fputc寫文件函數把一個字符寫到磁盤文件上去。其一般調用形fputc寫文件函數在前面介紹過putchar函數,其實putchar是從fputc函數派生出來的。putchar(c)是在stdio.h文件中用預處理命令#define定義的宏:#defineputchar(c)fputc(c,stdout)前面已敘述,stdout是系統定義的文件指針變量,它與終端輸出相連。fputc(c,stdout)的作用是將c的值輸出到終端。用宏putchar(c)比寫fputc(c,stdout)簡單一些。從用戶的角度,可以把putchar(c)看作函數而不必嚴格地稱它為宏。fputc寫文件函數在前面介紹過putchar函數,其實pufgetc讀文件函數從指定的文件讀入一個字符,該文件必須是以讀或讀寫方式打開的。fgetc函數的調用形式為 ch=fgetc(fp);fp為文件型指針變量,ch為字符變量。fgetc函數帶回一個字符,賦給ch。如果在執行fgetc函數讀字符時遇到文件結束符,函數返回一個文件結束標志EOF(-1)。如果想從一個磁盤文件順序讀入字符并在屏幕上顯示出來,可以: ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp);}fgetc讀文件函數從指定的文件讀入一個字符,該文件必須是以feof()判斷文件是否結束函數注意:EOF不是可輸出字符,因此不能在屏幕上顯示。由于字符的ASCII碼不可能出現-1,因此EOF定義為-1是合適的。當讀入的字符值等于-1(即EOF)時,表示讀入的已不是正常的字符而是文件結束符。但以上只適用于讀文本文件的情況?,F在ANSIC已允許用緩沖文件系統處理二進制文件,而讀入某一個字節中的二進制數據的值有可能是-1,而這又恰好是EOF的值。這就出現了需要讀入有用數據而卻被處理為“文件結束”的情況。為了解決這個問題,ANSIC提供一個feof函數來判斷文件是否真的結束。 feof(fp)用來測試fp所指向的文件當前狀態是否“文件結束”。如果是文件結束,函數feof(fp)的值為1(真),否則為0(假)。feof()判斷文件是否結束函數注意:EOF不是可輸出字符,feof()判斷文件是否結束函數如: while(!feof(fp)) { c=fgetc(fp); …}feof()判斷文件是否結束函數如:fputc和fgetc舉例例12.1從鍵盤輸入一些字符,逐個把它們送到磁盤上去,直到輸入一個“#”為止。源碼參見12-1.c例12.2將一個磁盤文件中的信息復制到另一個磁盤文件中。源碼參見12-2\a.c使用命令行方式輸入兩個文件名;源碼參見12-2\b.cfputc和fgetc舉例例12.1從鍵盤輸入一些字符,逐fread和fwrite函數ANSIC標準提出設置兩個函數(fread和fwrite),用來讀寫一個數據塊。它們的一般調用形式為 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp);其中:buffer:是一個指針。對fread來說,它是讀入數據的存放地址。對fwrite來說,是要輸出數據的地址(以上指的是起始地址)。size:要讀寫的字節數。count:要進行讀寫多少個size字節的數據項。fp:文件型指針。如果fread或fwrite調用成功,則函數返回值為count的值,即輸入或輸出數據項的完整個數。fread和fwrite函數ANSIC標準提出設置兩個函數fread和fwrite函數如果文件以二進制形式打開,用fread和fwrite函數就可以讀寫任何類型的信息,如: fread(f,4,2,fp);其中f是一個實型數組名。一個實型變量占4個字節。這個函數從fp所指向的文件讀入2次(每次4個字節)數據,存儲到數組f中。fread和fwrite函數如果文件以二進制形式打開,用frfread和fwrite函數如果有一個如下的結構體類型: structstudent-type { charname[10]; intnum; intage; charaddr[30]; }stud[40];假設學生的數據已存放在磁盤文件中,可以用下面的for語句和fread函數讀入40個學生的數據: for(i=0;i<40;i++) { fread(&stud[i],sizeof(structstudent-type),1,fp); }同樣,以下for語句和fwrite函數可以將內存中的學生數據輸出到磁盤文件中去: for(i=0;i<40,i++) { fwrite(&stud[i],sizeof(structstudent-type),1,fp); }fread和fwrite函數如果有一個如下的結構體類型:fread和fwrite函數舉例例12.3從鍵盤輸入4個學生的有關數據,然后把它們轉存到磁盤文件上去。源碼參見12-3fread和fwrite函數舉例例12.3從鍵盤輸入4個學其它讀寫函數自學。其它讀寫函數自學。(五)文件的定位(五)文件的定位文件中有一個位置指針,指向當前讀寫的位置。如果順序讀
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論