1 / 37

CH-10

CH-10. 檔案處理 V2. 檔案觀念. 「 檔案 」( Files )是儲存在電腦周邊裝置的位元組資料集合,通常是儲存在軟硬磁碟機的資料,程式可以將輸出的資料儲存在檔案中保存,或是將檔案視為輸入資料讀取檔案內容,檔案的位元組資料可能被解譯成字元、數值、整數、字串或資料庫的記錄,取決於程式開啟的檔案存取類型。 C 語言標準函式庫的「檔案 I/O 」( File Input/Output )函數可以處理二種檔案類型: 文字和二進位檔案 。. 文字檔案.

stu
Download Presentation

CH-10

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CH-10 檔案處理 V2

  2. 檔案觀念 • 「檔案」(Files)是儲存在電腦周邊裝置的位元組資料集合,通常是儲存在軟硬磁碟機的資料,程式可以將輸出的資料儲存在檔案中保存,或是將檔案視為輸入資料讀取檔案內容,檔案的位元組資料可能被解譯成字元、數值、整數、字串或資料庫的記錄,取決於程式開啟的檔案存取類型。 • C語言標準函式庫的「檔案I/O」(File Input/Output)函數可以處理二種檔案類型:文字和二進位檔案。

  3. 文字檔案 • 文字檔案儲存的是字元資料,文字檔案視為一種「文字串流」(Text Stream),串流可以想像成水龍頭流出的是一個個字元,也就是說處理文字檔案只能向前一個個循序處理字元,也稱為「循序檔案」(Squential Files),如同水往低處流,並不能回頭處理之前處理過的字元。 • 文字檔案的處理 • 讀取(Input) • 寫入(Output) • 新增(Append)(如同輸出)

  4. 文字檔案的讀寫 • 開啟與關閉文字檔案 • 讀寫字串到文字檔案 • 讀寫字元到文字檔案 • 格式化讀寫文字檔案

  5. 開檔與關檔 • 開檔 • FILE *fopen(char *filename, char *mode) • FILE *fp; • fp = fopen(“aa.txt”, “r”); • fp = fopen(“bb.txt”,”w”); • fp = fopen(“cc.txt”,”a”); • 關檔 • int fclose(FILE *fp); • fclose(fp);

  6. File mode • r • w • a • r+ • w+ • a+

  7. 檢查檔案是否開啟 if ( fp == NULL ) { printf("檔案開啟失敗....\n"); exit(1); }

  8. 從文字檔案讀寫字串 • intfputs(char *str,FILE *fp); • fputs(line , fp); /* 寫入字串 */ • char *fgets(char *str, int num, FILE *fp ) • fgets(line, 50 ,fp); /* 讀出字串*/

  9. 讀取整個檔案內容 While ( fgets(line, 50 ,fp) != NULL ) { ………………… }

  10. 從文字檔案讀寫字元 • int putc(int ch , FILE *fp); • putc(line[j] , fp); /* 寫入字元 */ • chargetc(FILE *fp); • c =getc(fp); /* 讀出字元 */ while ((c = getc(fp)) != EOF ) putchar(c);

  11. 格式化讀寫 • int fprintf(FILE *fp, char * control , …..); • fprintf(fp, "%d: %s\n", i+1, line); • intfscanf(FILE *fp, char * control , …..); • fscanf(fp,"%s", line );

  12. 開關檔範例 #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { FILE *fp; if ( argc <= 2 ) { printf("使用: Ch10-2-1.exe filename mode\n"); exit(1); /* 錯誤, 結束程式 */ } fp = fopen(argv[1], argv[2]); if ( fp == NULL ) { /* 檔案開啟失敗 */ printf("檔案[%s]開啟失敗....\n", argv[1]); exit(1); /* 錯誤, 結束程式 */ } else { printf("開啟檔案:[%s]\n", argv[1]); printf("檔案模式:[%s]\n", argv[2]); } fclose(fp); /* 關閉檔案 */ }

  13. ex01結果

  14. 讀寫字串範例 #include <stdio.h> main() { FILE *fp; char filename[20] = "../bb.txt"; char line[50] = "KSU ELE\n"; char *c; int i, count; fp = fopen(filename, "w"); printf("開始寫入檔案%s....\n", filename); for ( i = 0; i < 5; i++) fputs(line , fp); /* 寫入字串 */ printf("寫入檔案結束!\n"); fclose(fp); /* 關閉檔案 */ fp = fopen(filename, "r"); if ( fp != NULL ) { count = 0; while( fgets(line, 50 ,fp) != NULL ) { printf("%s", line); /* 顯示文字內容 */ count++; } printf("一共讀取%d行文字內容\n", count); fclose(fp); /* 關閉檔案 */ } else printf("檔案開啟錯誤...\n"); getchar(); }

  15. 讀寫字元範例 #include <stdio.h> main() { FILE *fp; char filename[20] = "../bb.txt"; char line[50] = "崑山科技大學\n"; char c; int i, j; fp = fopen(filename, "a"); printf("開始寫入檔案%s....\n", filename); for ( i = 0; i < 5; i++) for ( j = 0; line[j] != '\0'; j++ ) putc(line[j] , fp); /* 寫入字元 */ printf("寫入檔案結束!\n"); fclose(fp); /* 關閉檔案 */ fp = fopen(filename, "r"); if ( fp != NULL ) { /* 讀取檔案 */ while ((c = getc(fp))!= EOF ) putchar(c); fclose(fp); /* 關閉檔案 */ } else printf("檔案開啟錯誤...\n"); getchar(); }

  16. 格式化讀寫範例 #include <stdio.h> main() { FILE *fp; char filename[20] = "../bb.txt"; char line[50] = "我愛C語言"; int i; char c; fp = fopen(filename, "w"); printf("開始寫入檔案%s....\n", filename); for ( i = 0; i < 5; i++) /* 格式化輸出 */ fprintf(fp, "%d: %s\n", i+1, line); printf("寫入檔案結束!\n"); fclose(fp); /* 關閉檔案 */ fp = fopen(filename, "r"); if ( fp != NULL ) { /* 讀取檔案 */ while ( fscanf(fp,"%s", line) != EOF ) printf("%s\n", line); fclose(fp); /* 關閉檔案 */ } else printf("檔案開啟錯誤...\n"); getchar(); }

  17. 產生5個亂數,寫至test1_982.txt //產生5個亂數,介於5至100之間,寫至test1_982.txt ex10.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define random( x) rand() % x void main(int argc, char *argv[]) { int i,j; int a[5]; char buf[10]; FILE *fp; fp = fopen("test1_982.txt","w"); srand(time(NULL) % 50); for (i=0; i < 5 ; i++) { a[i] = 1 + random(100 - 5 + 1 ); printf("%d ", a[i]); itoa(a[i],buf,10); //整數變字串 fputs(buf,fp); fputs("\n",fp); } fclose(fp); }

  18. 產生5個亂數,寫至test2_982.txt //產生5個亂數,介於5至100之間,寫至test2_982.txt ex11.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define random( x) rand() % x void main(int argc, char *argv[]) { int i,j; int a[5]; FILE *fp; fp = fopen("test2_982.txt","w"); srand(time(NULL) % 50); for (i=0; i < 5 ; i++) { a[i] = 1 + random(100 - 5 + 1 ); printf("%5d\n", a[i]); fprintf(fp,“%5d\n”,a[i]); //重點 } fclose(fp); getch(); }

  19. 輸入5個字串寫至檔案 //輸入5個字串,寫至test3_982.txt ex12.c #include <stdio.h> void main(int argc, char *argv[]) { int i; char buf[50]; FILE *fp; fp = fopen("test3_982.txt","w"); for (i=0; i < 5 ; i++) { gets(buf); fputs(buf , fp); /* 寫入字串 */ putc('\n' , fp); } fclose(fp); getch(); }

  20. 顯示檔案內容 //顯示檔案內容,test3_982.txt ex12.c #include <stdio.h> void main(int argc, char *argv[]) { int i; char buf[50]; FILE *fp; fp = fopen("test3_982.txt","r"); while( fgets(buf, 50 ,fp) != NULL ) printf("%s", buf); /* 顯示文字內容 */ fclose(fp); getch(); }

  21. 統計字母個數 //統計字母個數,test3_982.txt ex14.c #include <stdio.h> void main(int argc, char *argv[]) { int i,s=0; char buf[50]; FILE *fp; fp = fopen("test3_982.txt","r"); while( fgets(buf, 50 ,fp) != NULL ) { printf("%s", buf); /* 顯示文字內容 */ s += count_letter(buf); } fclose(fp); printf("\n 字母共有%d個",s); getch(); }

  22. 統計字母個數2 int count_letter(char *p) { int c=0; while ( *p ) { if ( islower(*p) ) c++; p++; } return c; }

  23. 二進位檔案 • 沒有處理過的「位元組」(Bytes)資料 • 二進位檔案可以依需求以循序或「隨機存取」(Random Access)方式進行處理,隨機處理可以將檔案視為一個儲存在記憶體的陣列或結構陣列,只需移動「檔案指標」(File Pointer)到存取的位置,就可以存取資料,如同在陣列使用索引存取陣列元素。

  24. 二進位檔案的讀寫 • 二進位檔案讀寫除了可以使用文字檔案的循序方式存取,還可以使用隨機方式,以記錄為單位進行存取,能夠隨機存取任一筆記錄或更改指定記錄的資料。

  25. 二進位檔案的讀寫 FILE *fp; fp = fopen("filename", "wb");

  26. 開啟模式 • rb • wb • r+b • w+b

  27. 結構 • 隨機存取是以記錄為存取單位,在建立二進位檔案的隨機存取前,C程式需要宣告結構來儲存資料,例如:學生資料的record結構,如下所示: struct record { char name[20]; int age; float score; }; typedef struct recordstudent;

  28. 二進位檔案-相關函數 /* 開啟檔案新增內容 */ fp = fopen(filename, "r+b"); /* 寫入檔案 */ fwrite(&std, sizeof(std), 1, fp); /* 搜尋指定記錄的檔案指標位置 */ fseek(fp, rec*sizeof(std) , SEEK_SET); /* 讀取檔案 */ result = fread(&std, sizeof(std), 1, fp); /* 輸出緩衝區 */ fflush(fp); /* 關閉檔案 */ fclose(fp);

  29. feof()函數 • feof()函數是用來檢查是否讀到檔尾 while ( !feof(fp) ) { …………… }

  30. fseek()函數 • fseek()函數的offset參數是位移量,可以使用記錄數和結構大小計算而得,如下所示: fseek(fp, rec*sizeof(std), SEEK_SET); • 程式碼是從SEEK_SET位置的檔案開頭開始,位移量是rec*sizeof(std)位元組數,其中rec是記錄編號從0開始,使用sizeof運算子計算結構大小,即記錄尺寸,origin參數值有三種,如下: • SEEK_SET:從檔案開頭。 • SEEK_CUR:從檔案現在的位置。 • SEEK_END:從檔案結尾。

  31. 寫入記錄到二進位檔(ex06) #include <stdio.h> #include <string.h> struct record { char name[20]; int age; float score; }; typedef struct record student; void addrecord(FILE *, char *, int, int); main() { FILE *fp; student std; char filename[20] = "ex06.dat"; fp = fopen(filename, "wb"); printf("開始寫入檔案%s....\n", filename); addrecord(fp, "陳小安", 22, 65.5); addrecord(fp, "江小魚", 21, 78.9); addrecord(fp, "張無忌", 20, 67.8); printf("已經寫入3筆記錄!\n"); fclose(fp); /* 關閉檔案 */ getchar(); }

  32. 寫入記錄到二進位檔(ex06)2 void addrecord(FILE *fp, char *name, int age, int score) { student temp; /* 指定結構的成員變數 */ strcpy(temp.name, name); temp.age = age; temp.score = score; /* 寫入檔案 */ fwrite(&temp, sizeof(temp), 1, fp); }

  33. 循序讀取檔案的記錄(ex07) #include <stdio.h> struct record { char name[20]; int age; float score; }; typedef struct record student; main() { FILE *fp; student std; char filename[20] = "../ex06.dat"; fp = fopen(filename, "rb"); if ( fp != NULL ) /* 檢查是否有錯誤 */ { while ( !feof(fp) ) /* 是否是檔尾 */ { if ( fread(&std, sizeof(std), 1, fp) ) { /* 顯示記錄資料 */ printf("姓名: %s\n", std.name); printf("年齡: %d\n", std.age); printf("成績: %6.2f\n", std.score); printf("--------------------\n"); } } fclose(fp); /* 關閉檔案 */ } else printf("檔案開啟錯誤...\n"); getchar(); }

  34. 隨機讀取檔案範例(ex05) #include <stdio.h> #include <stdlib.h> struct record { char name[20]; int age; float score; }; typedef struct record student; main() { FILE *fp; student std; int rec, result, doedit; float score; char filename[20] = "../ex06.dat"; fp = fopen(filename, "r+b"); if ( fp == NULL ) /* 檢查是否有錯誤 */ { printf("檔案開啟錯誤...\n"); exit(1); }

  35. 隨機讀取2 printf("請輸入記錄編號[0-2]? "); scanf("%d", &rec); while ( rec >= 0 ) { fseek(fp, rec*sizeof(std), SEEK_SET); printf("目前的檔案位置: %ld\n", ftell(fp)); result = fread(&std, sizeof(std), 1, fp); if (result==1) { /* 顯示記錄資料 */ printf("--------------------\n"); printf("姓名: %s\n", std.name); printf("年齡: %d\n", std.age); printf("成績: %6.2f\n", std.score); printf("--------------------\n"); printf("是否更改成績?(1為是, 0為否)"); scanf("%d", &doedit); if ( doedit == 1 ) { /* 更改成績 */ printf("請輸入新成績? "); scanf("%f", &score); std.score = score; /* 搜尋指定記錄的檔案指標位置 */ fseek(fp, rec*sizeof(std), SEEK_SET); /* 寫入檔案 */ fwrite(&std, sizeof(std), 1, fp); fflush(fp); /* 輸出緩衝區 */

  36. 隨機讀取3 } } else printf("\n記錄編號: %d 找不到!\n", rec); printf("請輸入記錄編號[0-2]? "); scanf("%d", &rec); } fclose(fp); /* 關閉檔案 */ getchar(); }

More Related