檔案1.0
檔案的詳細介紹
引子
檔案.在我們前面學習通訊錄時,程式運行起來時,可以給通訊錄增刪查改,但此時資料是存放在記憶體中,當程式退出時,通訊錄的資料就消失了,
就很難受,為了使得資料持久化,我們就應該把資料存放在磁盤檔案,存放到資料庫等方式,磁盤上關機了重啟還會在,使資料持久化,因此就需要用到檔案
目錄
檔案
目錄
檔案
1.什么是檔案
2.檔案名
3.檔案指標(檔案的打開與關閉)
4.檔案的使用
1 什么是檔案
在磁盤上所有的東西都是檔案,c盤包括桌面的,
但一般在程式設計時,分兩種:程式檔案和資料檔案(從檔案的功能進行分類的)
程式檔案有源程式檔案.c,目標檔案.obj,可執行檔案.exe
資料檔案,我們寫的資料
2.檔案名
檔案名,一個檔案有唯一的檔案標識,便于用戶使用和識別(絕對路徑)
檔案名包含3個部分:檔案路徑+檔案名主干+檔案名后綴
如c:\code\test.txt,其中c:\code\是路徑名,test叫檔案主干名,.txt叫檔案的后綴2
3.檔案指標
4.檔案指標(檔案的打開與關閉)
每個被使用的檔案都開辟了一個相應的檔案資訊區,用于存放檔案的相關資訊,
(如檔案的名字,檔案狀態及檔案當前的位置)這些資訊都保持在一個結構體變數中,該結構體型別名叫FILE
一般用FILE型指標來維護FILE結構的變數,這樣使用起來更加方便
FILE* pf,pf是指向FILE型的變數,可以使用pf來指向某個檔案資訊區,通過檔案資訊區中的資訊就可以訪問該檔案,即可以通過檔案指標變數找到與他相關的檔案,
4.檔案的使用
檔案在讀寫之前首先要打開檔案fopen,在檔案使用完之后要關閉檔案fclose,fopen回傳失敗會回傳一個空指標,因此每次使用都要判斷
其中fopen原型是FILE * fopen(const char * path, const char * mode);
const char * path是使用的路徑,即要在哪個檔案中使用
const char * mode是fopen的打開形式
常見的模式有”r“,(read)以只讀方式打開檔案,該檔案必須存在,
”w“(write)打開只寫檔案,若檔案存在則檔案長度清為零,即該檔案內容會消失;若檔案不存在則創建該檔案,
例如
1.0
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *pf=fopen("tst.dat", "w");*///"test.dat"是檔案名,"w"是打開方式(以寫的形式進行創建)(只寫)“w”為了 輸出資料,打開一個檔案,如果指定檔案不存在,就新建一個(在此檔案中開辟)
if (pf == NULL)
{
perror("fopen");
return 1;
}
//寫檔案
//關閉檔案(不想要了)
fclose(pf);
pf = NULL;//可類比動態記憶體開辟,補不置成空指標就會報錯
return 0;
}
1.1
#include<stdio.h>
int main()
{
FILE *pf=fopen("D:\\2021\\class\\test.7\\test.dat", "w");//如果檔案并不是在此檔案下創建的化,同樣也不會運行成功,但使用絕對路徑是可以的
//,單斜杠情況下會將后面理解為轉義字符,因此都要使用雙斜杠,用于將\列印出來
if (pf == NULL)
{
perror("fopen");
return 1;
}
//寫檔案
//關閉檔案(不想要了)
fclose(pf);
pf = NULL;//
return 0;
}
1.3
#include<stdio.h>
int main()
{
FILE *pf = fopen("tst.dat", "r");//以讀的方式打開
if (pf == NULL)
{
perror("fopen");
return 1;
}
//寫檔案
//關閉檔案(不想要了)
fclose(pf);
pf = NULL;//可類比動態記憶體開辟,
return 0;
}
檔案的順序讀寫
:流,高度抽象的概念,,我們寫的程式有時想放螢屏,硬碟,u盤,光碟,網路,程式要操作各種硬體,也就需要各種的讀寫方式,因此在程式與硬體中抽象出流這個層次
我們只有把資料放到流里面去,寫檔案可以理解為檔案流,
c語言程式運行起來,就默認打開了3個流
stdin-標準輸入流--鍵盤, stdout標準輸出流--螢屏, stderr--標準錯誤流--螢屏,型別都是FILE*的使用哪個流就在哪個流輸出輸入
代碼2.0
#include<stdio.h>
int main()
{
FILE *pf = fopen("test.dat", "w");//以w的形式打開,即使原來有內容也會清空掉,
if (pf == NULL)
{
perror("fopen");
return 1;
}
//寫檔案
fputc('b', pf);//檔案字符輸入,
fputc('i', pf);
fputc('t', pf);//便會向test.dat檔案中輸入bit
// 關閉檔案
fclose(pf);
pf = NULL;
return 0;
}
2.1
#include<stdio.h>
int main()
{
fputc('c', stdout);//便在螢屏上列印了c這字符
fputc('b', stdout);
fputc('a', stdout);
return 0;
}
2.2.
#include<stdio.h>
int main()
{
FILE *pf = fopen("test.dat", "r");//以w的形式打開,即使原來有內容也會清空掉,
if (pf == NULL)
{
perror("fopen");
return 1;
}
//讀檔案,fgetc從檔案首字符中一個一個讀取
//int ret=fgetc(pf);//從檔案流里面讀一個字符,可以從檔案,也可以從標準輸入流中,檔案字符輸入,如果讀取正常,會回傳此字符的ascll值,如果讀取失敗,會回傳EOF(-1)
//printf("%c", ret);
//ret = fgetc(pf);
//printf("%c", ret);//讀取的都是test.dat
int ret = fgetc(stdin);//從標準螢屏輸入流里面讀一個字符,可以從檔案,也可以從標準輸入流中,檔案字符輸入,如果讀取正常,會回傳此字符的ascll值,如果讀取失敗,會回傳EOF(-1)
printf("%c", ret);
ret = fgetc(stdin);
printf("%c", ret);//讀取的都是test.dat,檔案結束就會輸出EOF為-1
fclose(pf);
pf = NULL;
return 0;
}
我們不僅可以一個字符一個字符的輸入與輸出,
我們也可以一行一行的輸入與輸出
可以用到fgets,fputs
#include<stdio.h>
int main()
{
FILE*pf = fopen("test.dat", "w");//以寫的形式打開
if (pf == NULL)
{
perror("fopen");
return 1;
}
//寫檔案-按行寫
fputs("abcdef\n",pf);//s-string寫字串打個\n就可以換行,pf是要寫的檔案流
fputs("ghijk\n", pf);
//用完關閉檔案
fclose(pf);
pf = NULL;
return 0;
}
#include<stdio.h>
int main()
{
char arr[10] = { 0 };
FILE*pf = fopen("test.dat", "r");//以讀的形式打開
if (pf == NULL)
{
perror("fopen");
return 1;
}
//讀檔案-按行讀
fgets(arr, 4, pf);//fgets(const char*string,const int n,const stream),n是可以讀的最大字符,但多了一個\0n要+1
printf("%s\n", arr);//讀完從c后開始讀
fgets(arr, 4, pf);//最多讀3個
printf("%s\n", arr);
//用完關閉檔案
fclose(pf);
pf = NULL;
return 0;
}
我們接下來介紹一下fprintf,fscanf,sscanf,sprintf
#include<stdio.h
struct s
{
char age[10];
int a;
float f;
};
int main()
{
struct s a = { "hello",20,5.5f };
char buf[100] = { 0 };
struct s tmp = { 0 };
//sprintf是把格式化的資料轉化成字串,
sprintf(buf, "%s %d %f", a.age, a.a, a.f);
printf("%s\n", buf);
//從buf這個字串中還原出一個結構體
//從字串中讀出格式化的資料
sscanf(buf, "%s %d %f", tmp.age, &tmp.a, &tmp.f);
printf("%s %d %f", tmp.age, tmp.a, tmp.f);
return 0;
}
fprintf(FILE *stream, const char *format,......)除去前面的流,后都和printf一樣,
struct a
{
char arr[10];
int num;
float sc;
};
int main()
{
struct a s = { "abcd",10,5.5f };
FILE* pf = fopen("test.dat", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fprintf(pf, "%s %d %f", s.arr, s.num, s.sc);//格式化輸出,寫入pf檔案流,
return 0;
}
fscanf同scanf多了前面的流
int main()
{
struct a s = { "abcd",10,5.5 };
FILE* pf = fopen("test.dat", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fscanf(pf, "%s %d %f", s.arr, &(s.num), &(s.sc));//格式化輸出,寫入pf檔案流
printf("%s %d %f", s.arr, s.num, s.sc);
return 0;
}
fwrite二進制輸出 (const void *ptr, size_t size, size_t nmemb, FILE *stream)
把 ptr 所指向的陣列中的資料寫入到給定流 stream 中
size這是要被寫入的每個元素的大小,以位元組為單位
nmemb -- 這是元素的個數,每個元素的大小為 size 位元組
int main()
{
struct a s = { "abcd",10,5.5 };
FILE* pf = fopen("test.dat", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fwrite(&s, sizeof(struct a), 1, pf);//二進制輸出,寫入pf檔案流
fclose(pf);
pf = NULL;
return 0;
}
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)與fwrite等同二進制輸出
int main()
{
struct a s = { "abcd",10,5.5 };
FILE* pf = fopen("test.dat", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fread(&s, sizeof(struct a), 1, pf);//二進制輸入,讀出pf檔案流
printf("%s %d %f", s.arr, s.num, s.sc);
fclose(pf);
pf = NULL;
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/323055.html
標籤:其他
