SlideShare una empresa de Scribd logo
1 de 33
Descargar para leer sin conexión
檔案處理
 資料流
 檔案概述
 檔案處理函式
Revised on July 14, 2021
Make
each
day
count
 資料的輸入與輸出都必須透過電腦的週邊設備
 不同週邊設備對資料輸入/輸出格式和方法有不同處理方式,增加撰寫
資料檔存取程式的困難度,且易生週邊設備彼此不相容的問題。C 語
言透過資料流來解決這個問題
 資料流就是將傳輸的資料視為⼀串連續的位元組的流動,簡化⾼階輸
出入動作,使得輸出入動作都在資料流上運作,撰寫資料檔內資料的
輸出入程式時,可不用理會週邊裝置的多樣性
資料流 (Data Stream) 1/3
Make
each
day
count
資料流 (Data Stream) 2/3
 資料流藉檔案指標移動來存取資料流上資料
 檔案指標為目前所指資料位置。資料經過存取後檔案指標會往後移動
 每個資料檔最後⾯都有⼀個檔案結束符號EOF,用來告知該資料檔到
此結束後⾯沒有資料,若檔案指標指到 EOF 表示資料已經存取完畢
'C' 'p' 'r' 'o' 'g' 'r' 'a' 'm' 'm' 'i' 'n' 'g' … EOF
檔案指標
資料流可視為一串連續的字位元組
Make
each
day
count
 電腦週邊設備資料存取可採用二進位檔 (binary file) 或文字檔 (text file)
 二進位檔內的資料是採二進位格式儲存,例如:聲音檔(*.wav)、影像
檔(*.avi)、執行檔(*.exe)、圖形檔(*.png)
 採二進位格式儲存檔案較省儲存空間
 文字檔內的每個字元都用該字元對應 ASCII 碼格式進行存檔,⼀個字
元的 ASCII 碼就佔用 1 Byte,10 個字元就佔用 10 Bytes
 採文字檔的格式進行存檔會較浪費儲存空間
資料流 (Data Stream) 3/3
Make
each
day
count
 檔案處理在電腦裡的概念就是在處理檔案 I/O (Input/Output),也就
是檔案的輸入與輸出
 檔案輸入看成為讀取檔案 (read),檔案輸出看成為寫入檔案 (write)
 從資料流的觀點,對檔案的寫入或讀出就是對資料流的寫入與讀出
檔案處理的概念
記憶體 檔案
輸出 (Output)
輸入 (Intput)
Make
each
day
count
 循序檔 (sequential file) 全名為循序存取檔 (sequential acess file) ,此
種資料在寫入時是從資料檔的開頭開始按照資料寫入的先後順序逐筆
寫入磁碟中,每⼀筆資料的⼤⼩可以不相同
 讀取循序檔時必須從第⼀筆開始逐筆往後讀取,⼀直到檔案結束為⽌
 循序檔每筆資料⻑度不拘,較節省磁碟空間,查詢資料時都必須從第
⼀筆開始找起較費時間
循序檔與隨機檔 1/2
資料1 資料2 資料3 資料4 資料5 ........
讀取 讀取 讀取 讀取 讀取
不是我要
的資料
不是我要
的資料
不是我要
的資料
不是我要
的資料
我要的就是它!
檔案資料流
Make
each
day
count
 隨機檔 (random file) 全名為隨機存取檔 (random access file)
 隨機檔⼤都使用結構方式來存放資料,由於每筆資料⻑度是相同,存
取此種資料不管資料是位於最前⾯、中間或最後⾯,都是經過計算便
可直接存取該筆資料,而是採跳躍式直接存取,不像循序檔找尋資料
時都必須從最開頭開始找起
循序檔與隨機檔 2/2
資料1 資料2 資料3 資料4 資料5 ........
讀取
我要的就是它!
檔案資料流
直接跳到定位
Make
each
day
count
 檔案被開啟後,系統會配置⼀塊記憶體當作檔案資料存取的緩衝區
 緩衝區 (buffer) 讓檔案的部分資料先讀取到此區中,⼀旦需要存取資
料時,先到此區中尋找或暫時的寫入
 如果緩衝區中找不到要讀取的資料,或者寫入的資料已經滿了 (超過緩
衝區的⼤⼩),系統才會到磁碟機中尋找或真正的寫入檔案中
檔案資料緩衝區
記憶體
檔案
緩衝區不足應付需求
時才實際存取檔案
緩衝區
(buffer)
C program
檔案作業
存取緩衝區
Make
each
day
count
 C語言使用檔案位置指標來記錄目前檔案資料流中的讀寫位置
 移動此指標到檔案資料流中適當的位置,再透過檔案處理函式,就可
以控制存取檔案資料
 只要調整檔案位置指標,
 為了提供隨機檔的存取機制,在檔案結構FILE中提供了檔案位置指標
_ptr記錄目前檔案讀寫的位置
檔案位置指標
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
Make
each
day
count
 文字檔有容易分享、解讀,但在有些應用上特別適合使用二進位檔
 所儲存數據本身是二進位模式,例如儲存圖片,點陣圖(Bitmap graphic) ,
以RGB碼來代表每⼀個像素的顏⾊,例如 (60,101,168),代表的是⼀個類近
於海軍藍的顏⾊。因此,要儲存⼀幅圖,就是儲存了幾百萬個像素,每⼀
個像素都是⼀個⼩於255的數字,最適合的自然是用二進位儲存
 所儲存的數據需要壓縮以縮⼩檔案⼤⼩,微軟新格式的.docx檔其實是⼀個
特殊的壓縮檔,將其中所有內容 (包括巨集,加在文件中的圖片),通通加
到該壓縮檔中,因此可以減少佔用空間。 .docx、.pptx、xlsx的二進位制式
都是因為這個原因。Mac的 .numbers 檔都是基於同⼀個原理。
 電腦是使用二進位運算,因此任何執行檔,例如 Windows 的 exe 檔,都是
二進位檔
文字檔與二進位檔 2/2
11
Make
each
day
count
 C函式庫中提供的檔案處理函式都宣告在 stdio.h 檔
檔案處理函式
函式 說明
fopen 開啟檔案
fclose 關閉檔案
fgetc 從檔案資料流讀取一個字元
fputc 寫入一個字元到檔案資料流
fgets 從檔案資料流讀取字串
fputs 寫入字串到檔案資料流
fscanf 依照格式從檔案資料流讀取資料
fprintf 依照格式寫入資料到檔案資料流
fileno 回傳所開啟檔案對應的檔案處理代碼 (file handle no)
filelength 回傳檔案處理代碼所對應檔案的檔案大小 (bytes)
fwrite 寫入結構資料到檔案資料流
fread 從檔案資料流讀取結構資料
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
Make
each
day
count
 "a+" 開啟⼀個可以讀寫的檔案,若檔案已存在,新增的資料會附加在該
檔案的最後⾯;若檔案不存在,則自動建立⼀個新檔
 "r+"開啟⼀個可以讀寫的已存在檔案,若檔案不存在,回傳NULL
 "wb+" 開啟⼀個可以讀寫的二進位檔案,若檔案已存在,該檔內的資料
會被清空;若檔案不存在,則自動建立⼀個新檔
 "ab+" 開啟⼀個可以讀寫的二進位檔案,若檔案已存在,新增的資料會
附加在該檔案的最後⾯;若檔案不存在,則自動建立⼀個新檔
 "rb+" 開啟⼀個可以讀寫的已存在二進位檔案,若檔案不存在,回傳
NULL
開啟檔案 2/3
Make
each
day
count
 檔案被開啟後將以⼀個FILE型態的指標作為操作控制者,它就是⼀個
指向這個檔案處理的相關資訊的指標
 後續對檔案進行I/O處理時,皆須使用這個檔案指標來處理
 FILE的原型宣告如下:
typedef struct _iobuf {
char*_ptr;
int _cnt;
char*_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char*_tmpfname;
} FILE;
開啟檔案 3/3
Make
each
day
count
 int fclose (FILE *fptr);
 檔案關閉成功則傳回 0,失敗則傳回-1
 檔案開啟後若不再繼續使用,要記得使用 fclose() 函式將指定的檔案
關閉,並將FILE檔案結構指標的相關資源及所佔用的緩衝區歸還系統
 以讀取模式開啟的檔案,沒做關閉檔案的動作影響不⼤;但以寫入模式開
啟的檔案,若沒有使用 fclose() 關閉檔案,最後放在緩衝區的資料並不會
自動寫回資料檔內,而發生資料遺失的情形
關閉檔案 1/2
Make
each
day
count
 檔案開啟時,系統都會自動賦予該檔⼀個檔案處理代碼
 int fileno (FILE *fptr);
 回傳 fptr 檔案指標所對應的檔案處理代碼
 必須引用 stdlib.h 標頭檔
 long filelength (int handle_no);
 回傳檔案處理代碼所對應檔案的檔案⼤⼩,以bytes為單位
 必須引用 io.h 標頭檔
檢查檔案大小
17
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
Make
each
day
count
 int fgetc( FILE *stream );
 從檔案中讀取⼀個字元
 讀取成功時傳回所讀取字元的 ASCII 碼,以整數型態傳回之;若已經讀取
到檔案結束標記 EOF 或讀取失敗將傳回 EOF (值為 -1)
 int fputc( int c, FILE *stream );
 寫入⼀個字元到檔案資料流
 寫入成功時傳回所寫入字元的 ASCII 碼,以整數型態傳回之;若寫入失敗
則傳回EOF (值為 -1)
字元方式讀寫檔案 1/2
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
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
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
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
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#include <io.h>
void test_formatio(){
FILE *fptr;
char path[] = "d:MEGAnotesCexamples12 Filetest.txt";
char pid[5], pname[20], str_price[5];
int fno, fsize, price = 0;
char op;
讀寫格式化文字檔 2/5
24
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
Make
each
day
count
while (1) {
printf("繼續新增資料(Y/N)?");
if (toupper(getche()) == 'Y'){
printf("n編號:");
gets(pid);
printf("品名:");
gets(pname);
printf("單價:");
gets(str_price);
fprintf(fptr, "%s %s %dn", pid, pname, atoi(str_price));
}
else {
fclose(fptr);
break;
}
}
讀寫格式化文字檔 4/5
26
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
Make
each
day
count
 使用fopen函式來開啟,在開啟模式的字串中,必須加上’b’字元
9-4.1 二進位檔的開啟
//開啟二進位檔test1.bin供寫入
FILE *fp1=fopen(“test1.bin”,”wb”);
//開啟二進位檔test2.bin供讀取
FILE *fp2=fopen(“test2.bin”,”rb”);
//開啟二進位檔test3.bin供增添
FILE *fp3=fopen(“test3.bin”,”ab”);
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
Make
each
day
count
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define NUMBER 5
struct record{
char name[8];
char id[5];
float chinese;
float english;
float math;
};
讀寫二進位檔 2/4
30
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
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
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

Más contenido relacionado

La actualidad más candente

プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~Takuya Akiba
 
暗号文のままで計算しよう - 準同型暗号入門 -
暗号文のままで計算しよう - 準同型暗号入門 -暗号文のままで計算しよう - 準同型暗号入門 -
暗号文のままで計算しよう - 準同型暗号入門 -MITSUNARI Shigeo
 
MySQL Index勉強会外部公開用
MySQL Index勉強会外部公開用MySQL Index勉強会外部公開用
MySQL Index勉強会外部公開用CROOZ, inc.
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化Gosuke Miyashita
 
CRDT in 15 minutes
CRDT in 15 minutesCRDT in 15 minutes
CRDT in 15 minutesShingo Omura
 
内製ツールを使ったチート診断・脆弱性診断
内製ツールを使ったチート診断・脆弱性診断内製ツールを使ったチート診断・脆弱性診断
内製ツールを使ったチート診断・脆弱性診断DeNA
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~Takuya Akiba
 
ブロックチェーン系プロジェクトで着目される暗号技術
ブロックチェーン系プロジェクトで着目される暗号技術ブロックチェーン系プロジェクトで着目される暗号技術
ブロックチェーン系プロジェクトで着目される暗号技術MITSUNARI Shigeo
 
Code Formula 2014 予選A 解説
Code Formula 2014 予選A 解説Code Formula 2014 予選A 解説
Code Formula 2014 予選A 解説AtCoder Inc.
 
Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Kwen Won Lee
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界Preferred Networks
 
シリコンバレーでエンジニア就職する前に知りたかったこと
シリコンバレーでエンジニア就職する前に知りたかったことシリコンバレーでエンジニア就職する前に知りたかったこと
シリコンバレーでエンジニア就職する前に知りたかったことTatsuya Nanjo
 

La actualidad más candente (20)

プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
 
RC4&RC5
RC4&RC5RC4&RC5
RC4&RC5
 
暗号文のままで計算しよう - 準同型暗号入門 -
暗号文のままで計算しよう - 準同型暗号入門 -暗号文のままで計算しよう - 準同型暗号入門 -
暗号文のままで計算しよう - 準同型暗号入門 -
 
MySQL Index勉強会外部公開用
MySQL Index勉強会外部公開用MySQL Index勉強会外部公開用
MySQL Index勉強会外部公開用
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
 
CRDT in 15 minutes
CRDT in 15 minutesCRDT in 15 minutes
CRDT in 15 minutes
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
内製ツールを使ったチート診断・脆弱性診断
内製ツールを使ったチート診断・脆弱性診断内製ツールを使ったチート診断・脆弱性診断
内製ツールを使ったチート診断・脆弱性診断
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
 
ブロックチェーン系プロジェクトで着目される暗号技術
ブロックチェーン系プロジェクトで着目される暗号技術ブロックチェーン系プロジェクトで着目される暗号技術
ブロックチェーン系プロジェクトで着目される暗号技術
 
Avl tree
Avl treeAvl tree
Avl tree
 
新しい暗号技術
新しい暗号技術新しい暗号技術
新しい暗号技術
 
Code Formula 2014 予選A 解説
Code Formula 2014 予選A 解説Code Formula 2014 予選A 解説
Code Formula 2014 予選A 解説
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
フラグを愛でる
フラグを愛でるフラグを愛でる
フラグを愛でる
 
シリコンバレーでエンジニア就職する前に知りたかったこと
シリコンバレーでエンジニア就職する前に知りたかったことシリコンバレーでエンジニア就職する前に知りたかったこと
シリコンバレーでエンジニア就職する前に知りたかったこと
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 

Similar a C語言檔案處理

10 檔案說明與處理
10 檔案說明與處理10 檔案說明與處理
10 檔案說明與處理shademoon
 
File api
File apiFile api
File apiTom Fan
 
探索 Everything 背后的技术
探索 Everything 背后的技术探索 Everything 背后的技术
探索 Everything 背后的技术yiwenshengmei
 
[系列活動] 手把手教你R語言資料分析實務
[系列活動] 手把手教你R語言資料分析實務[系列活動] 手把手教你R語言資料分析實務
[系列活動] 手把手教你R語言資料分析實務台灣資料科學年會
 
Practical data analysis in R: from data collection to data insight
Practical data analysis in R: from data collection to data insight Practical data analysis in R: from data collection to data insight
Practical data analysis in R: from data collection to data insight Chun-Min Chang
 
Practical Data Analysis in R
Practical Data Analysis in RPractical Data Analysis in R
Practical Data Analysis in RChun-Ming Chang
 
Device Driver - Chapter 3字元驅動程式
Device Driver - Chapter 3字元驅動程式Device Driver - Chapter 3字元驅動程式
Device Driver - Chapter 3字元驅動程式ZongYing Lyu
 
Fast Esp搜索系统
Fast Esp搜索系统Fast Esp搜索系统
Fast Esp搜索系统xiaochawan
 
Cfengine培训文档 刘天斯
Cfengine培训文档 刘天斯Cfengine培训文档 刘天斯
Cfengine培训文档 刘天斯liuts
 
Puppet安装测试
Puppet安装测试Puppet安装测试
Puppet安装测试Yiwei Ma
 
PHP & MySQL 教學
PHP & MySQL 教學PHP & MySQL 教學
PHP & MySQL 教學Bo-Yi Wu
 
Excelize云原生时代国产电子表格文档基础库的开源之路
Excelize云原生时代国产电子表格文档基础库的开源之路Excelize云原生时代国产电子表格文档基础库的开源之路
Excelize云原生时代国产电子表格文档基础库的开源之路Ri Xu
 
Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)
Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)
Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)rvillegasg
 

Similar a C語言檔案處理 (20)

第9章文件
第9章文件第9章文件
第9章文件
 
C语言
C语言C语言
C语言
 
10 檔案說明與處理
10 檔案說明與處理10 檔案說明與處理
10 檔案說明與處理
 
Flex国际化I18N解决方案
Flex国际化I18N解决方案Flex国际化I18N解决方案
Flex国际化I18N解决方案
 
File api
File apiFile api
File api
 
探索 Everything 背后的技术
探索 Everything 背后的技术探索 Everything 背后的技术
探索 Everything 背后的技术
 
Ch7 教學
Ch7 教學Ch7 教學
Ch7 教學
 
存储过程
存储过程存储过程
存储过程
 
[系列活動] 手把手教你R語言資料分析實務
[系列活動] 手把手教你R語言資料分析實務[系列活動] 手把手教你R語言資料分析實務
[系列活動] 手把手教你R語言資料分析實務
 
Practical data analysis in R: from data collection to data insight
Practical data analysis in R: from data collection to data insight Practical data analysis in R: from data collection to data insight
Practical data analysis in R: from data collection to data insight
 
Practical Data Analysis in R
Practical Data Analysis in RPractical Data Analysis in R
Practical Data Analysis in R
 
Overlayfs and VFS
Overlayfs and VFSOverlayfs and VFS
Overlayfs and VFS
 
Device Driver - Chapter 3字元驅動程式
Device Driver - Chapter 3字元驅動程式Device Driver - Chapter 3字元驅動程式
Device Driver - Chapter 3字元驅動程式
 
系統程式 -- 第 5 章
系統程式 -- 第 5 章系統程式 -- 第 5 章
系統程式 -- 第 5 章
 
Fast Esp搜索系统
Fast Esp搜索系统Fast Esp搜索系统
Fast Esp搜索系统
 
Cfengine培训文档 刘天斯
Cfengine培训文档 刘天斯Cfengine培训文档 刘天斯
Cfengine培训文档 刘天斯
 
Puppet安装测试
Puppet安装测试Puppet安装测试
Puppet安装测试
 
PHP & MySQL 教學
PHP & MySQL 教學PHP & MySQL 教學
PHP & MySQL 教學
 
Excelize云原生时代国产电子表格文档基础库的开源之路
Excelize云原生时代国产电子表格文档基础库的开源之路Excelize云原生时代国产电子表格文档基础库的开源之路
Excelize云原生时代国产电子表格文档基础库的开源之路
 
Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)
Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)
Windowsîä¼þïµí³¹ýâëçý¶¯¿ª·¢½ì³ì(µú¶þ°æ)
 

Más de 吳錫修 (ShyiShiou Wu)

mbot2.0教學-陀螺儀與三軸加速計應用.pdf
mbot2.0教學-陀螺儀與三軸加速計應用.pdfmbot2.0教學-陀螺儀與三軸加速計應用.pdf
mbot2.0教學-陀螺儀與三軸加速計應用.pdf吳錫修 (ShyiShiou Wu)
 
mbot2.0教學-四路顏色感測器應用.pdf
mbot2.0教學-四路顏色感測器應用.pdfmbot2.0教學-四路顏色感測器應用.pdf
mbot2.0教學-四路顏色感測器應用.pdf吳錫修 (ShyiShiou Wu)
 
mbot2.0教學-mblock5開發mBot 2.0應用程式.pdf
mbot2.0教學-mblock5開發mBot 2.0應用程式.pdfmbot2.0教學-mblock5開發mBot 2.0應用程式.pdf
mbot2.0教學-mblock5開發mBot 2.0應用程式.pdf吳錫修 (ShyiShiou Wu)
 

Más de 吳錫修 (ShyiShiou Wu) (20)

mbot2.0教學-陀螺儀與三軸加速計應用.pdf
mbot2.0教學-陀螺儀與三軸加速計應用.pdfmbot2.0教學-陀螺儀與三軸加速計應用.pdf
mbot2.0教學-陀螺儀與三軸加速計應用.pdf
 
mbot2.0教學-使用makeblock雲服務.pdf
mbot2.0教學-使用makeblock雲服務.pdfmbot2.0教學-使用makeblock雲服務.pdf
mbot2.0教學-使用makeblock雲服務.pdf
 
mbot2.0教學-局域網路傳輸應用.pdf
mbot2.0教學-局域網路傳輸應用.pdfmbot2.0教學-局域網路傳輸應用.pdf
mbot2.0教學-局域網路傳輸應用.pdf
 
mbot2.0教學-四路顏色感測器應用.pdf
mbot2.0教學-四路顏色感測器應用.pdfmbot2.0教學-四路顏色感測器應用.pdf
mbot2.0教學-四路顏色感測器應用.pdf
 
mbot2.0教學-聲光控制應用.pdf
mbot2.0教學-聲光控制應用.pdfmbot2.0教學-聲光控制應用.pdf
mbot2.0教學-聲光控制應用.pdf
 
mbot2.0教學-光感測器與LED應用.pdf
mbot2.0教學-光感測器與LED應用.pdfmbot2.0教學-光感測器與LED應用.pdf
mbot2.0教學-光感測器與LED應用.pdf
 
mbot2.0教學-超音波感測應用.pdf
mbot2.0教學-超音波感測應用.pdfmbot2.0教學-超音波感測應用.pdf
mbot2.0教學-超音波感測應用.pdf
 
mbot2.0教學-移動控制.pdf
mbot2.0教學-移動控制.pdfmbot2.0教學-移動控制.pdf
mbot2.0教學-移動控制.pdf
 
mbot2.0教學-mblock5開發mBot 2.0應用程式.pdf
mbot2.0教學-mblock5開發mBot 2.0應用程式.pdfmbot2.0教學-mblock5開發mBot 2.0應用程式.pdf
mbot2.0教學-mblock5開發mBot 2.0應用程式.pdf
 
mbot2.0教學-組裝與測試.pdf
mbot2.0教學-組裝與測試.pdfmbot2.0教學-組裝與測試.pdf
mbot2.0教學-組裝與測試.pdf
 
Python元組,字典,集合
Python元組,字典,集合Python元組,字典,集合
Python元組,字典,集合
 
Python函式
Python函式Python函式
Python函式
 
Python串列資料應用
Python串列資料應用Python串列資料應用
Python串列資料應用
 
Python 迴圈作業
Python 迴圈作業Python 迴圈作業
Python 迴圈作業
 
Python分支作業
Python分支作業Python分支作業
Python分支作業
 
Python基本資料運算
Python基本資料運算Python基本資料運算
Python基本資料運算
 
建置Python開發環境
建置Python開發環境建置Python開發環境
建置Python開發環境
 
micro:bit加速度感測應用
micro:bit加速度感測應用micro:bit加速度感測應用
micro:bit加速度感測應用
 
C語言列舉與聯合
C語言列舉與聯合C語言列舉與聯合
C語言列舉與聯合
 
C語言結構與串列
C語言結構與串列 C語言結構與串列
C語言結構與串列
 

C語言檔案處理

  • 1. 檔案處理  資料流  檔案概述  檔案處理函式 Revised on July 14, 2021
  • 2. Make each day count  資料的輸入與輸出都必須透過電腦的週邊設備  不同週邊設備對資料輸入/輸出格式和方法有不同處理方式,增加撰寫 資料檔存取程式的困難度,且易生週邊設備彼此不相容的問題。C 語 言透過資料流來解決這個問題  資料流就是將傳輸的資料視為⼀串連續的位元組的流動,簡化⾼階輸 出入動作,使得輸出入動作都在資料流上運作,撰寫資料檔內資料的 輸出入程式時,可不用理會週邊裝置的多樣性 資料流 (Data Stream) 1/3
  • 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
  • 5. Make each day count  檔案處理在電腦裡的概念就是在處理檔案 I/O (Input/Output),也就 是檔案的輸入與輸出  檔案輸入看成為讀取檔案 (read),檔案輸出看成為寫入檔案 (write)  從資料流的觀點,對檔案的寫入或讀出就是對資料流的寫入與讀出 檔案處理的概念 記憶體 檔案 輸出 (Output) 輸入 (Intput)
  • 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 ........ 讀取 我要的就是它! 檔案資料流 直接跳到定位
  • 8. Make each day count  檔案被開啟後,系統會配置⼀塊記憶體當作檔案資料存取的緩衝區  緩衝區 (buffer) 讓檔案的部分資料先讀取到此區中,⼀旦需要存取資 料時,先到此區中尋找或暫時的寫入  如果緩衝區中找不到要讀取的資料,或者寫入的資料已經滿了 (超過緩 衝區的⼤⼩),系統才會到磁碟機中尋找或真正的寫入檔案中 檔案資料緩衝區 記憶體 檔案 緩衝區不足應付需求 時才實際存取檔案 緩衝區 (buffer) C program 檔案作業 存取緩衝區
  • 9. Make each day count  C語言使用檔案位置指標來記錄目前檔案資料流中的讀寫位置  移動此指標到檔案資料流中適當的位置,再透過檔案處理函式,就可 以控制存取檔案資料  只要調整檔案位置指標,  為了提供隨機檔的存取機制,在檔案結構FILE中提供了檔案位置指標 _ptr記錄目前檔案讀寫的位置 檔案位置指標
  • 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
  • 11. Make each day count  文字檔有容易分享、解讀,但在有些應用上特別適合使用二進位檔  所儲存數據本身是二進位模式,例如儲存圖片,點陣圖(Bitmap graphic) , 以RGB碼來代表每⼀個像素的顏⾊,例如 (60,101,168),代表的是⼀個類近 於海軍藍的顏⾊。因此,要儲存⼀幅圖,就是儲存了幾百萬個像素,每⼀ 個像素都是⼀個⼩於255的數字,最適合的自然是用二進位儲存  所儲存的數據需要壓縮以縮⼩檔案⼤⼩,微軟新格式的.docx檔其實是⼀個 特殊的壓縮檔,將其中所有內容 (包括巨集,加在文件中的圖片),通通加 到該壓縮檔中,因此可以減少佔用空間。 .docx、.pptx、xlsx的二進位制式 都是因為這個原因。Mac的 .numbers 檔都是基於同⼀個原理。  電腦是使用二進位運算,因此任何執行檔,例如 Windows 的 exe 檔,都是 二進位檔 文字檔與二進位檔 2/2 11
  • 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
  • 14. Make each day count  "a+" 開啟⼀個可以讀寫的檔案,若檔案已存在,新增的資料會附加在該 檔案的最後⾯;若檔案不存在,則自動建立⼀個新檔  "r+"開啟⼀個可以讀寫的已存在檔案,若檔案不存在,回傳NULL  "wb+" 開啟⼀個可以讀寫的二進位檔案,若檔案已存在,該檔內的資料 會被清空;若檔案不存在,則自動建立⼀個新檔  "ab+" 開啟⼀個可以讀寫的二進位檔案,若檔案已存在,新增的資料會 附加在該檔案的最後⾯;若檔案不存在,則自動建立⼀個新檔  "rb+" 開啟⼀個可以讀寫的已存在二進位檔案,若檔案不存在,回傳 NULL 開啟檔案 2/3
  • 15. Make each day count  檔案被開啟後將以⼀個FILE型態的指標作為操作控制者,它就是⼀個 指向這個檔案處理的相關資訊的指標  後續對檔案進行I/O處理時,皆須使用這個檔案指標來處理  FILE的原型宣告如下: typedef struct _iobuf { char*_ptr; int _cnt; char*_base; int _flag; int _file; int _charbuf; int _bufsiz; char*_tmpfname; } FILE; 開啟檔案 3/3
  • 16. Make each day count  int fclose (FILE *fptr);  檔案關閉成功則傳回 0,失敗則傳回-1  檔案開啟後若不再繼續使用,要記得使用 fclose() 函式將指定的檔案 關閉,並將FILE檔案結構指標的相關資源及所佔用的緩衝區歸還系統  以讀取模式開啟的檔案,沒做關閉檔案的動作影響不⼤;但以寫入模式開 啟的檔案,若沒有使用 fclose() 關閉檔案,最後放在緩衝區的資料並不會 自動寫回資料檔內,而發生資料遺失的情形 關閉檔案 1/2
  • 17. Make each day count  檔案開啟時,系統都會自動賦予該檔⼀個檔案處理代碼  int fileno (FILE *fptr);  回傳 fptr 檔案指標所對應的檔案處理代碼  必須引用 stdlib.h 標頭檔  long filelength (int handle_no);  回傳檔案處理代碼所對應檔案的檔案⼤⼩,以bytes為單位  必須引用 io.h 標頭檔 檢查檔案大小 17
  • 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
  • 24. Make each day count #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <conio.h> #include <io.h> void test_formatio(){ FILE *fptr; char path[] = "d:MEGAnotesCexamples12 Filetest.txt"; char pid[5], pname[20], str_price[5]; int fno, fsize, price = 0; char op; 讀寫格式化文字檔 2/5 24
  • 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
  • 26. Make each day count while (1) { printf("繼續新增資料(Y/N)?"); if (toupper(getche()) == 'Y'){ printf("n編號:"); gets(pid); printf("品名:"); gets(pname); printf("單價:"); gets(str_price); fprintf(fptr, "%s %s %dn", pid, pname, atoi(str_price)); } else { fclose(fptr); break; } } 讀寫格式化文字檔 4/5 26
  • 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
  • 28. Make each day count  使用fopen函式來開啟,在開啟模式的字串中,必須加上’b’字元 9-4.1 二進位檔的開啟 //開啟二進位檔test1.bin供寫入 FILE *fp1=fopen(“test1.bin”,”wb”); //開啟二進位檔test2.bin供讀取 FILE *fp2=fopen(“test2.bin”,”rb”); //開啟二進位檔test3.bin供增添 FILE *fp3=fopen(“test3.bin”,”ab”);
  • 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
  • 30. Make each day count #include <stdio.h> #include <stdlib.h> #include <conio.h> #define NUMBER 5 struct record{ char name[8]; char id[5]; float chinese; float english; float math; }; 讀寫二進位檔 2/4 30
  • 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