Download presentation
Presentation is loading. Please wait.
1
程式設計 博碩文化出版發行
2
第十章 檔案的輸入與輸出 課前指引 當C的程式執行完畢之後,所有儲存在記憶體的資料都會消失,這時如果需要將執行結果儲存在不會揮發的儲存媒體上(如硬碟等),必須透過檔案模式來加以保存。
3
章節大綱 10-1 有緩衝區的輸入與輸出函數 10-2 無緩衝區的輸入與輸出 10-3 檔案的應用與實務 備註:可依進度點選小節
4
10-1 有緩衝區的輸入與輸出函數 C的檔案處理函數主要區分為以下兩大類: 有緩衝區的輸出與輸入 無緩衝區的輸出與輸入
5
10-1 有緩衝區的輸入與輸出函數 有緩衝區的輸出入函數如下所示:
6
10-1 有緩衝區的輸入與輸出函數 fopen()與fclose()函數
C語言中必須透過FILE型態的指標來操作檔案開關讀寫。FILE是一種指標型態,宣告方式如下: FILE所定義的指標變數用來指向目前stream的位置,所以C語言中有關於檔案輸出入的函數,多數都需搭配宣告此資料型態運用。 FILE *stream;
7
10-1 有緩衝區的輸入與輸出函數 fopen()與fclose()函數
接下來要進行檔案存取,首先必須開啟資料流,也就是進行開啟檔案的動作。也就是說,所有的檔案讀寫動作,都必須先開啟檔案,才能再繼續接下來的讀寫動作。指令如下: FILE * fopen ( const char * filename const char * mode );
8
10-1 有緩衝區的輸入與輸出函數 fopen()與fclose()函數 參數說明 filename:指定檔案名稱。
Mode是指:開啟檔案的模式,至於開啟模式字串,在文字檔的存取上主要以六種模式為主,如下表所示:
9
10-1 有緩衝區的輸入與輸出函數 fopen()與fclose()函數
參數說明 stream:指定資料流物件指標 當資料流正確被關閉時,回傳數值為0,如果資料流關閉錯誤,將引發錯誤或是回傳EOF。 int fclose ( FILE * stream );
10
10-1 有緩衝區的輸入與輸出函數 範例CH10_01.c
11
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱為 pFile。 第8行是以讀取方式開啟檔案。
第9行透過判斷指標變數是否為NULL來確認檔案是否存在。 第11行開啟檔案後程式結束前,應透過fclose()函數關閉檔案。
12
10-1 有緩衝區的輸入與輸出函數 範例CH10_02.c
13
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第8行以讀取方式開啟檔案。
第11行關閉檔案。
14
10-1 有緩衝區的輸入與輸出函數 fputc()函數。當寫入字元失敗時,則傳回EOF值,否則就傳回所寫入的字元。fputc()函數只會將參數中的字元寫入資料流,一次一個字元。指令如下: 參數說明 character:字元代表的ASCII碼。 stream: 指定資料流物件指標。 int fputc ( int character, FILE * stream );
15
10-1 有緩衝區的輸入與輸出函數 範例CH10_03.c
16
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第8行以寫入方式開啟檔案。
第11行以putc()函數寫入一個字元,ASCII為65。
17
10-1 有緩衝區的輸入與輸出函數 範例CH10_04.c
18
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第9行以寫入方式開啟檔案。
第12~13行以for迴圈與putc()函數將資料儲存到所指定的檔案。
19
10-1 有緩衝區的輸入與輸出函數 fgetc()函數
fgetc()函數可從檔案資料流中一次讀取一個字元,然後將讀取游標往下一個字元移動,讀取字元正常時,回傳該字元ASCII碼。讀取完後指標會指向下一個位址,並且逐步將檔案的內容讀出。當需要更有效率的讀取或處理資料時,可使用此函數。指令如下: 參數說明 stream: 指定資料流物件指標。 int fgetc ( FILE * stream );
20
10-1 有緩衝區的輸入與輸出函數 範例 CH10_05.c
21
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第10行以讀取方式開啟檔案。
第13~16行EOF值利用while迴圈與EOF值執行判斷式,並逐字讀出檔案中資料。
22
10-1 有緩衝區的輸入與輸出函數 範例CH10_06.c
23
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第8行檢查檔案是否開啟成功。 第11行利用while迴圈判斷檔案是否讀取完畢。
第12行一次讀取一個字元,逐步將文字檔內容讀出。
24
10-1 有緩衝區的輸入與輸出函數 fputs()函數與fgets()函數
例如: fputs("寫入字串", 檔案指標變數); File *fptr; char str[20]; ….. fputs(str,fptr);
25
10-1 有緩衝區的輸入與輸出函數 範例CH10_07.c
26
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第8行以新增方式開啟檔案。
第11行以fputs()函數寫入資料到指定的檔案中。
27
10-1 有緩衝區的輸入與輸出函數 範例 CH10_08.c
28
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第9~10行分別開啟要讀取與寫入的兩個檔案。 第12行檢查檔案是否開啟成功。
第15行使用while迴圈判斷檔案fptr是否讀取完畢。 第17行str[31]是用來儲存‘\0’。 第19行將str字串寫入到fptr1檔案中。
29
10-1 有緩衝區的輸入與輸出函數 fprintf()函數
寫入檔案的fprintf()函數,與printf()函數不同在於printf()輸出到螢幕上,fprintf()可指定到特定的資料流物件。指令如下: 參數說明 stream: 指定資料流物件指標。 format:格式化的字串,同printf()函數設定。 例如: int fprintf ( FILE * stream, const char * format, ... ); File *fptr; int math,eng; float average; fprintf(fptr, "%d\t%d\t%f\n",math,enf,average);
30
10-1 有緩衝區的輸入與輸出函數 範例 CH10_09.c
31
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第8行宣告存放字串的字元陣列。
第10行寫入方式開啟檔案。 第15行以gets()函數輸入字串。利用格式化寫入函數fprint()將字串資料寫入檔案。
32
10-1 有緩衝區的輸入與輸出函數 fscanf()函數
fscanf()函數與scanf()函數相當類似,只是scanf()函數是由使用者的鍵盤輸入取得資料,而fscanf()函數則由檔案中讀取所指定的資料。也就是由資料流讀取資料。並設定參數代號,可透過此函數,反向的將資料參考(reference)到指定的變數中。指令如下: int fscanf ( FILE * stream, const char * format, ... );
33
fprintf()函數與fscanf()函數
10-1 有緩衝區的輸入與輸出函數 fprintf()函數與fscanf()函數 參數說明 stream: 指定資料流物件指標。 format:格式化的字串。如下所示
34
10-1 有緩衝區的輸入與輸出函數 範例 CH10_10.c
35
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。
第9行以可讀取或寫入方式開啟檔案。 第13行以fprintf()函數寫入資料。 第15行以scanf()函數讀取資料。
36
10-1 有緩衝區的輸入與輸出函數 fwrite()函數
參數說明 p:資料區塊的指標。 s:每個元素的資料大小。 c:總資料數量。 stream: 指定資料流物件指標。 例如: size_t fwrite ( const void * p, size_t s, size_t c, FILE * stream ); File *fptr; char str[20]; int count; fwrite(str,sizeof(char),count,fptr);
37
10-1 有緩衝區的輸入與輸出函數 範例 CH10_11.c
38
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個指標形態的變數,變數名稱pFile。 第9行以寫入方式開啟檔案。
第12行利用gets()函數取得使用者輸入的資料。 第13行利用fwrite()函數以區塊方式寫入資料。
39
10-1 有緩衝區的輸入與輸出函數 fread()函數
如果想要讀取fwrite()函數所寫入的資料內容,就必須採取fread()函數來讀取檔案,才可以正確讀出有意義的資訊。指令如下: 參數說明 p:資料區塊的指標。 s:每個元素的資料大小。 c:總資料數量。 stream: 指定資料流物件指標。 size_t fread ( void * p, size_t s, size_t c, FILE * stream );
40
10-1 有緩衝區的輸入與輸出函數 範例CH10_12.c
41
10-1 有緩衝區的輸入與輸出函數 範例CH10_12.c
42
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第6行宣告一個字元型態的指標變數。 第7行宣告固定長度的字元陣列。
第15行以 fread()函數回傳值表示讀取資料的長度。 第16行在字串陣列中加入NULL的字元表示結束。 第24行以fread()函數讀取資料流時,直接指定字元型態指標,以存放讀入的資料。
43
10-1 有緩衝區的輸入與輸出函數 fseek函數與rewind()函數 當每次使用檔案存取函數一次,檔案讀取游標都會往下一個位置移動。
例如像fgetc()函數讀取完畢後會移動一個位元組,而在fgets()函數中,由於我們的lentgh長度為10,所以它一次會讀取9個位元組的長度(因為最後一個位元組必須填入'\0'),像這種讀取方式,可稱之為循序式讀取。其實檔案中也可以藉由fseek()函數來操作讀取游標。指令如下: int fseek ( FILE * stream, long int os, int o );
44
10-1 有緩衝區的輸入與輸出函數 fseek函數與rewind()函數 參數說明 stream: 指定資料流物件指標。 os:位移量。
45
10-1 有緩衝區的輸入與輸出函數 fseek函數與rewind()函數 例如: File *fptr;
fseek(fptr,10,SEEK_SET); /* 從檔案開頭向後計算10個位元組 */ fseek(fptr,10,SEEK_CUR); /* 目前的游標位置向後計算10個位元組 */ fseek(fptr,10,SEEK_END); /* 從檔案尾端向前計算10個位元組 */
46
10-1 有緩衝區的輸入與輸出函數 範例CH10_13.c
47
10-1 有緩衝區的輸入與輸出函數 範例CH10_13.c
48
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第10~14行建立A~Z的資料於fileIO.txt檔案中。
第21~25行利用for迴圈,共執行五次。 第24行利用fseek()函數,每次跳躍3個間格。
49
10-1 有緩衝區的輸入與輸出函數 範例CH10_14.c
50
10-1 有緩衝區的輸入與輸出函數 範例CH10_14.c
51
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第7行宣告str字元陣列。
第16行SEEK_SET常數的應用,第18行SEEK_CUR常數的應用。 第21行SEEK_END常數的應用。
52
10-1 有緩衝區的輸入與輸出函數 fseek函數與rewind()函數
參數說明 stream: 指定資料流物件指標。 rewind()函數功能等同下列程式: void rewind ( FILE * stream); fseek ( stream , 0L , SEEK_SET );
53
10-1 有緩衝區的輸入與輸出函數 範例CH10_15.c
54
10-1 有緩衝區的輸入與輸出函數 範例CH10_15.c
55
10-1 有緩衝區的輸入與輸出函數 執行結果 程式解說 第10~14行建立A~Z的資料於fileIO.txt檔案中。
第24行執行迴圈時,每次皆跳回資料流起點,固定輸出都讀到第一個字元。
56
10-2 無緩衝區的輸入與輸出 使用無緩衝區的輸入與輸出函數需引用fcntl.h此標頭檔,所以在程式碼最上方需加入如下引用敘述:
關於無緩衝區的輸入與輸出指令函數,整理如下表: #include<fcntl.h>
57
10-2 無緩衝區的輸入與輸出 open()函數與close()函數
參數說明 filename:欲開啟的檔案名稱。 int open(char *filename, int mode, int access);
58
10-2 無緩衝區的輸入與輸出 open()函數與close()函數 參數說明 mode:欲開啟檔案的模式。如下表所示:
59
10-2 無緩衝區的輸入與輸出 open()函數與close()函數 參數說明 例如:
access:存取模式,指定存取的方式,一般狀況只需設定為0即可。 例如: O_WRONLY| O_APPEND /* 開啟檔案,但只能寫入附加資料 */ O_RDONLY| O_TEXT /* 開啟唯讀的文字檔 */
60
10-2 無緩衝區的輸入與輸出 範例CH10_16.c
61
10-2 無緩衝區的輸入與輸出 執行結果 程式解說 第8行開啟指定檔名的檔案,模式為唯讀。 第10行當回傳為-1表示失敗。
本第17行程式執行時,已經存在fileIO.txt檔,所以結果是成功。
62
10-2 無緩衝區的輸入與輸出 open()函數與close()函數
close()函數主要是用來關閉一個以開啟的檔案。一般搭配open()函數使用。當open()函數開啟檔案時,會回傳一個int型態的檔案代碼,再透過close()含數關閉此代碼所代表的檔案。宣告方式如下: 參數說明 fileID:表示檔案代碼。 例如: int close(int fileID); close(fpt1);
63
10-2 無緩衝區的輸入與輸出 範例CH10_17.c
64
10-2 無緩衝區的輸入與輸出 範例CH10_17.c
65
10-2 無緩衝區的輸入與輸出 執行結果 程式解說 第3行開啟模式常數所定義的標頭檔。 第7~8行宣告並設定兩個檔案名稱。
第11~13行宣告兩個int型態值來記錄開啟的檔案ID碼。 第27、32行檢查close()的回傳值,為0時表示成功。
66
10-2 無緩衝區的輸入與輸出 read()函數與write()函數 read()函數主要用來讀出檔案中的資料,宣告方式如下: 參數說明
fileID:準備要讀取的檔案代碼。 *buff:存放讀入資料的暫存區指標。 length:讀入資料的長度。 例如: int read(int fileID,void *buff,int length); bytes=read(fptl, buffer, sizeof(buffer));/* 從fpt1檔案,每次讀取256個位元組,bytes為實際的傳回讀取位元組 */
67
10-2 無緩衝區的輸入與輸出 範例CH10_18.c
68
10-2 無緩衝區的輸入與輸出 執行結果 程式解說 第3行定義一個常數,代表讀取長度。 第10行宣告int型態值來記錄開啟的檔案ID碼。
第13行確認檔案開啟成功。 第15行確認檔案讀取成功。
69
10-2 無緩衝區的輸入與輸出 read()函數與write()函數 write()函數主要是用來將資料寫入檔案,宣告方式如下: 參數說明
fileID:準備要寫入的檔案代碼。 *buff:存放寫入資料的暫存區指標。 length:寫入資料的長度。 例如: int wirte(int fileID,void *buff,int length); write(fpt1, buffer, sizeof(buffer)); /* 在fpt1檔案,每次寫入256個位元組 */
70
10-2 無緩衝區的輸入與輸出 範例CH10_19.c
71
10-2 無緩衝區的輸入與輸出 執行結果 程式解說 第8行定義一個檔名變數。 第9行定義一個準備寫入資料的變數。
第15行開啟指定的檔名,若是沒有建立此檔案,並可供讀寫。 第17行利用write()函數將資料寫入檔案。
72
10-2 無緩衝區的輸入與輸出 lseek()函數
無緩衝區隨機檔存取方式也可以在檔案的任何地方配合檔案游標位置,作隨機存取資料。在C中,提供了lseek()函數來移動與操作讀取游標,到游標所指定的新位置讀取或寫入資料。lseek()函數使用方法與觀念類是fseek(),只是使用的地方不同,fseek()適用有緩衝區的輸入與輸出;lseek()適用無緩衝區的輸入與輸出。 宣告方式如下: int lseek(int fileID,long offset,int position);
73
10-2 無緩衝區的輸入與輸出 lseek()函數 參數說明 fileID:檔案代碼。
offset:偏移量。依據position的位置偏移量,不可超過64K。 position:偏移的起始位置。可設定以下參數:
74
10-2 無緩衝區的輸入與輸出 範例 CH10_20.c
75
10-2 無緩衝區的輸入與輸出 執行結果 程式解說 第9行定義一個字元陣列。 第13行開啟指定的檔名,若是沒有建立此檔案,並可供讀寫。
第15~20行迴圈共執行四次。 第17行寫入buff代表的資料至檔案。
76
10-3 檔案的應用與實務 簡易資料庫的資料增刪與修改
本小節中我們將定義一個結構型態所建立的簡易客戶資料庫,主要用來記錄客戶的相關資料,並可透過迴圈不斷的提供使用者挑選功能項目,直到按下“4”才結束選單的挑選模式。
77
10-3 檔案的應用與實務 範例CH10_21.c
78
10-3 檔案的應用與實務 範例CH10_21.c
79
10-3 檔案的應用與實務 範例CH10_21.c
80
10-3 檔案的應用與實務 範例CH10_21.c
81
10-3 檔案的應用與實務 範例CH10_21.c
82
10-3 檔案的應用與實務 範例CH10_21.c
83
10-3 檔案的應用與實務 範例CH10_21.c
84
10-3 檔案的應用與實務 執行結果
85
10-3 檔案的應用與實務 程式解說 第4~9行定義一個structure,主要用來記錄客戶的相關資料。
第16~55行是主程式區塊。透過迴圈不斷的提供使用者挑選功能項目,直到按下“4”才結束選單的挑選模式。 第33~49行利用switch控制輸入的挑選資訊應該執行的自訂函數。 第64、66、68行透過scanf()函數擷取使用者輸入的資料。 第72~83行:透過自訂函數isExist()來檢查目前新增的資料是否已存在。若是存在,顯示提示訊息,反之,則正常寫入檔案。 第93行以唯讀的方式開啟資料檔。 第97行透過feof()函數來判斷檔案指標是否以讀取到檔案末端。
86
本章結束 Q&A討論時間
Similar presentations