Weitere ähnliche Inhalte
Mehr von 吳錫修 (ShyiShiou Wu) (20)
C語言檔案處理
- 3. Make
each
day
count
資料流 (Data Stream) 2/3
資料流藉檔案指標移動來存取資料流上資料
檔案指標為目前所指資料位置。資料經過存取後檔案指標會往後移動
每個資料檔最後⾯都有⼀個檔案結束符號EOF,用來告知該資料檔到
此結束後⾯沒有資料,若檔案指標指到 EOF 表示資料已經存取完畢
'C' 'p' 'r' 'o' 'g' 'r' 'a' 'm' 'm' 'i' 'n' 'g' … EOF
檔案指標
資料流可視為一串連續的字位元組
- 4. Make
each
day
count
電腦週邊設備資料存取可採用二進位檔 (binary file) 或文字檔 (text file)
二進位檔內的資料是採二進位格式儲存,例如:聲音檔(*.wav)、影像
檔(*.avi)、執行檔(*.exe)、圖形檔(*.png)
採二進位格式儲存檔案較省儲存空間
文字檔內的每個字元都用該字元對應 ASCII 碼格式進行存檔,⼀個字
元的 ASCII 碼就佔用 1 Byte,10 個字元就佔用 10 Bytes
採文字檔的格式進行存檔會較浪費儲存空間
資料流 (Data Stream) 3/3
- 6. Make
each
day
count
循序檔 (sequential file) 全名為循序存取檔 (sequential acess file) ,此
種資料在寫入時是從資料檔的開頭開始按照資料寫入的先後順序逐筆
寫入磁碟中,每⼀筆資料的⼤⼩可以不相同
讀取循序檔時必須從第⼀筆開始逐筆往後讀取,⼀直到檔案結束為⽌
循序檔每筆資料⻑度不拘,較節省磁碟空間,查詢資料時都必須從第
⼀筆開始找起較費時間
循序檔與隨機檔 1/2
資料1 資料2 資料3 資料4 資料5 ........
讀取 讀取 讀取 讀取 讀取
不是我要
的資料
不是我要
的資料
不是我要
的資料
不是我要
的資料
我要的就是它!
檔案資料流
- 7. Make
each
day
count
隨機檔 (random file) 全名為隨機存取檔 (random access file)
隨機檔⼤都使用結構方式來存放資料,由於每筆資料⻑度是相同,存
取此種資料不管資料是位於最前⾯、中間或最後⾯,都是經過計算便
可直接存取該筆資料,而是採跳躍式直接存取,不像循序檔找尋資料
時都必須從最開頭開始找起
循序檔與隨機檔 2/2
資料1 資料2 資料3 資料4 資料5 ........
讀取
我要的就是它!
檔案資料流
直接跳到定位
- 10. Make
each
day
count
文字檔 (text file) 以是資料以ASCII碼 (American Standard Code for
Information Interchange) 編碼方式儲存
數值32767,在文字檔會佔用5個bytes,內容如下:
可使用純文字編輯器開啟,檢視檔案內容
二進位檔直接將資料以二進位位元儲存
數值32767,在二進位檔會佔用2bytes,內容如下:
電腦是二進位運算,使用二元檔不僅佔用空間⼩,執行速度也較文字檔快
文字檔與二進位檔 1/2
00100001 00100000 00100101 00100100 00100101
'3' '2' '7' '6' '7'
01111111 11111111
- 12. Make
each
day
count
C函式庫中提供的檔案處理函式都宣告在 stdio.h 檔
檔案處理函式
函式 說明
fopen 開啟檔案
fclose 關閉檔案
fgetc 從檔案資料流讀取一個字元
fputc 寫入一個字元到檔案資料流
fgets 從檔案資料流讀取字串
fputs 寫入字串到檔案資料流
fscanf 依照格式從檔案資料流讀取資料
fprintf 依照格式寫入資料到檔案資料流
fileno 回傳所開啟檔案對應的檔案處理代碼 (file handle no)
filelength 回傳檔案處理代碼所對應檔案的檔案大小 (bytes)
fwrite 寫入結構資料到檔案資料流
fread 從檔案資料流讀取結構資料
- 13. Make
each
day
count
FILE *fopen (const char *filename, const char *mode);
開啟檔案,成功開啟時回傳檔案結構指標FILE *,若開啟失敗則傳回
NULL
mode:檔案開啟的模式字串
"r" 開啟的檔案僅供讀取 (read),若檔案不存在,回傳NULL
"w" 開啟⼀個可以寫入 (write) 的檔案,若檔案已存在,該檔內的資料
會被清空;若檔案不存在,則自動建立⼀個新檔
"a" 開啟⼀個可以寫入的檔案,若檔案已存在,新增的資料會附加
(append) 在該檔案的最後⾯;若檔案不存在,則自動建立⼀個新檔
"w+" 開啟⼀個可以讀寫的檔案,若檔案已存在,該檔內的資料會被清
空;若檔案不存在,則自動建立⼀個新檔
開啟檔案 1/3
- 16. Make
each
day
count
int fclose (FILE *fptr);
檔案關閉成功則傳回 0,失敗則傳回-1
檔案開啟後若不再繼續使用,要記得使用 fclose() 函式將指定的檔案
關閉,並將FILE檔案結構指標的相關資源及所佔用的緩衝區歸還系統
以讀取模式開啟的檔案,沒做關閉檔案的動作影響不⼤;但以寫入模式開
啟的檔案,若沒有使用 fclose() 關閉檔案,最後放在緩衝區的資料並不會
自動寫回資料檔內,而發生資料遺失的情形
關閉檔案 1/2
- 18. Make
each
day
count
FILE *fptr;
int fno, fsize;
fptr = fopen("d:MEGAnotesCexamples12 Filetest.txt", "r+");
if (fptr == NULL) {
printf("開檔失敗!");
}
else {
printf("開啟檔案n");
fno = fileno(fptr);
fsize = filelength(fno);
printf("檔案⼤⼩:%d bytes", fsize);
fclose(fptr);
}
關閉檔案 2/2
18
- 19. Make
each
day
count
int fgetc( FILE *stream );
從檔案中讀取⼀個字元
讀取成功時傳回所讀取字元的 ASCII 碼,以整數型態傳回之;若已經讀取
到檔案結束標記 EOF 或讀取失敗將傳回 EOF (值為 -1)
int fputc( int c, FILE *stream );
寫入⼀個字元到檔案資料流
寫入成功時傳回所寫入字元的 ASCII 碼,以整數型態傳回之;若寫入失敗
則傳回EOF (值為 -1)
字元方式讀寫檔案 1/2
- 20. Make
each
day
count
FILE *fptr;
char s[] = "This is a test string for fputc/fgetc function.";
int i = 0;
char c;
fptr = fopen("d:MEGAnotesCexamples12 Filetest.txt", "w");
while(s[i] != '0') {
fputc(s[i], fptr);
i++;
}
fclose(fptr);
fptr = fopen("d:MEGAnotesCexamples12 Filetest.txt", "r");
c = fgetc(fptr);
while(c != EOF) {
printf("%c", c);
c = fgetc(fptr);
}
字元方式讀寫檔案 2/2
20
- 21. Make
each
day
count
char *fgets (char *string, int n, FILE *stream);
從目前檔案資料流指標所在位置開始讀取 n-1 個字元,因為要保留最後⼀
個字元寫入字串結尾標記 '0'。若在過程中讀取到 newline 字元,也就是
換行字元 'n' 則將停⽌讀取
函式將傳回所讀取到的字串指標,並將字串儲存在string中。若讀到檔尾,
則會傳回NULL
int fputs (const char *string, FILE *stream);
寫入⼀個字串到檔案資料流
寫入正確的話會傳回非負整數,通常是0;若寫入錯誤則傳回EOF
字串方式讀寫檔案 1/2
- 22. Make
each
day
count
FILE *fptr;
char s[] = "This is a test string for fputs/fgets function.nC programming";
char s2[20];
fptr = fopen("d:MEGAnotesCexamples12 Filetest.txt", "w");
fputs(s, fptr);
fclose(fptr);
fptr = fopen("d:MEGAnotesCexamples12 Filetest.txt", "r");
while(fgets(s2, 20, fptr) != NULL) {
printf("%s", s2);
}
fclose(fptr);
字串方式讀寫檔案 2/2
22
- 23. Make
each
day
count
int fprintf( FILE *fptr, const char *format [, argument ]...);
依照format引數格式輸出資料到檔案資料流
寫入正確的話會傳輸出 (寫入) 到檔案資料流的 byte 數;若寫入錯誤則傳
回 -1 (EOF)
format引數用法與 printf() 函式用法相同
int fscanf( FILE *fptr, const char *format [, argument ]...);
依照format引數格式從檔案資料流讀取資料,並存入對應的argument引數
讀取成功的話會回傳所讀取的資料筆數;若讀取錯誤則傳回 -1 (EOF)
format引數用法與 scanf() 函式用法相同
讀寫格式化文字檔 1/5
- 25. Make
each
day
count
printf("請選擇項目1. 開新檔t2. 開舊檔:");
op = getche();
if (op == '1')
fptr = fopen(path, "w+");
else if (op == '2')
fptr = fopen(path, "a+");
else {
printf("n輸入錯誤");
return;
}
fno = fileno(fptr);
fsize = filelength(fno);
printf("n%s開檔完成n原檔案⼤⼩:%d bytesn", path, fsize);
讀寫格式化文字檔 3/5
25
- 27. Make
each
day
count
fptr = fopen(path, "r");
fno = fileno(fptr);
fsize = filelength(fno);
printf("n%s資料更新完成n目前檔案⼤⼩:%d bytesn", path, fsize);
while(fscanf(fptr, "%s %s %d", pid, pname, &price) != EOF) {
printf("%5s %20s %5dn", pid, pname, price);
}
fclose(fptr);
return;
}
讀寫格式化文字檔 5/5
27
- 29. Make
each
day
count
size_t fwrite(void *buffer, size_t size, size_t count, FILE *fptr);
將 buffer 中每組⼤⼩為 size (單位byte) 的資料,總共 count 組寫入到 fptr
檔案資料流中
傳回寫入的資料筆數
size_t fread(void *buffer, size_t size, size_t count, FILE *fptr);
從檔案資料流 fptr 中讀取每組⼤⼩為 size (單位是byte) 的資料 count 組,
並存入 buffer 中
傳回讀取到的資料筆數
讀寫二進位檔 1/4
- 31. Make
each
day
count
void test_structio(){
FILE *fptr;
char path[] = "d:MEGAnotesCexamples12 Filetest.txt";
char op;
int i;
struct record students[NUMBER] = {
{"王⼩明", "a001", 89, 90, 98}, {"李⼤同", "a002", 66, 87, 79},
{"周⼤雄", "a003", 88, 65, 80}, {"陳⼩強", "a004", 70, 91, 80},
{"徐⼩春", "a005", 77, 79, 82}};
struct record student;
printf("請選擇項目1. 更新檔案t2. 讀取檔案:");
op = getche();
if (op == '1') {
fptr = fopen(path, "wb");
fwrite(&students[0], sizeof(students[0]), NUMBER, fptr);
fclose(fptr);
printf("n資料更新完成");
}
讀寫二進位檔 3/4
31
- 32. Make
each
day
count
else if (op == '2') {
fptr = fopen(path, "rb");
printf("n姓名tt 學號tt 國文tt 英文tt 數學n");
while (fread(&student, sizeof(student), 1, fptr) == 1){
printf("%stt %stt %4.1ftt %4.1ftt %4.1fn", student.name,
student.id, student.chinese, student.english, student.math);
}
fclose(fptr);
}
else {
printf("n輸入錯誤");
}
return;
}
讀寫二進位檔 4/4
32
- 33. Make
each
day
count
void rewind (FILE *fptr);
重置檔案位置指標到檔案開頭
int fseek (FILE *fptr, long int offset, int whence);
移動檔案位置指標到指定位置
offset 移動偏移值,正數代表 fptr 由指定位置往後⾯移動,負數代表 fptr
由指定位置往前⾯移動
whence指定位置,SEEK_SET表示檔案開頭,SEEK_CUR表示目前fptr位
置,SEEK_END表示檔案結尾
int feof (FILE *fptr)
檢查 fptr 是否指向檔案結束位置
回傳值 0 表示 fptr 已至檔案結束位置
控制檔案位置指標
33