三種緩沖
1.全緩沖:在緩沖區(qū)寫滿時(shí)輸出到指定的輸出端. 比如對(duì)磁盤上的文件進(jìn)行讀寫通常是全緩沖的.
2.行緩沖:在遇到'\n'時(shí)輸出到指定的輸出端. 比如標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出就是行緩沖, 回車后就會(huì)進(jìn)行相應(yīng)的I/O操作.
3.無緩沖:有什么就輸出什么. 比如標(biāo)準(zhǔn)錯(cuò)誤輸出, 出錯(cuò)時(shí)立即顯示出來.
設(shè)置緩沖方式的函數(shù)有兩個(gè)犯祠,分別為setbuf,setvbuf
可用fflush立即輸出总处,不管緩沖區(qū)是否達(dá)到輸出標(biāo)準(zhǔn)
打開、關(guān)閉
1.FILE *fopen(const char *restrict pathname, const char *restrict type)
第一個(gè)參數(shù)為文件的路徑,
第二個(gè)參數(shù)為打開的方式: r/rb只讀; w/wb只寫; a/ab添加; r+/ra+讀寫; w+/wa+讀寫; a+/ab+文件尾添加讀寫
2.int fclose(FILE *fp)
關(guān)閉打開的文件流, 釋放內(nèi)存
讀寫終止判斷
讀寫終止分兩種情況, 讀寫到文件尾正常終止, 讀寫出錯(cuò)返回
int feof(FILE *fp): 如果是正常終止, 函數(shù)返回非0(true)值
int ferror(FILE *fp): 如果是出錯(cuò)終止, 函數(shù)返回非0(true)值
每次讀寫一個(gè)字符
getc/fgetc/getchar
putc/fputc/putchar
getchar和putchar對(duì)應(yīng)終端窗口的輸入輸出, 不用指定參數(shù)
getc和fgetc需要指定FILE *fp
void onechar(FILE *fp){
int ch;
while((ch=getc(fp)) != EOF){
if(putchar(ch) == EOF){
printf("output error");
exit(1);
}
}
if(ferror(fp)){
printf("file read error");
exit(1);
}
}
每次讀寫一行
fgets/gets
fputs/puts
gets/puts默認(rèn)對(duì)應(yīng)終端窗口的輸入輸出
注意: puts會(huì)在行尾插入添加一個(gè)'\n', 所以當(dāng)我們用puts打印文件時(shí),每行顯示時(shí)都有兩個(gè)'\n'(除最后一行外), 也就是每行內(nèi)容下面都會(huì)有一個(gè)空行
void oneline(FILE *fp){
char buf[1024];
while(fgets(buf,MAXLINE,fp) != NULL){
if(puts(buf) == EOF){
printf("output error");
exit(1);
}
}
if(ferror(fp)){
printf("read error");
exit(1);
}
}
每次讀寫一個(gè)對(duì)象
這種讀寫方式也稱為二進(jìn)制方式, 由我們自己設(shè)定一次讀幾個(gè)<b>字節(jié)</b>
- size_t fread(void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp)
參數(shù)含義:從fp讀取, 讀取的內(nèi)容寫到ptr指向的內(nèi)存, 每次讀取size個(gè)字符, 一共讀nobj次, 返回值為實(shí)際讀取的次數(shù) - size_t fwrite(const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp)
struct people{
char name[10];
int age;
};
void readstruct(){
struct people man;
FILE *fp;
if((fp=fopen("./test.txt","r")) == NULL){
printf("fopen error");
exit(1);
}
if(fread(&man,sizeof(struct people),1,fp) != 1){
printf("fread error");
exit(1);
}
printf("name=%s, age=%d\n",man.name,man.age);
fclose(fp);
}
void writestruct(){
struct people man;
int i;
sprintf(man.name,"charlotte");
man.age=20;
FILE *fp;
if((fp=fopen("./test.txt","w+")) == NULL){
printf("fopen error");
exit(1);
}
if(fwrite(&man,sizeof(struct people),1,fp) != 1){
printf("fwrite error");
exit(1);
}
fclose(fp);
}
跳轉(zhuǎn)
創(chuàng)建一個(gè)文件, 然后寫入一些內(nèi)容, 這時(shí)文件指針在文件尾,
如果想用這個(gè)文件指針讀取剛剛寫入的內(nèi)容, 就需要先將文件指針移動(dòng)文件頭部
void rewind(FILE *fp)
將文件指針移動(dòng)文件頭
void fseek(FILE*fp, long offset, int whence)
隨意移動(dòng)到哪里
whence為初步移動(dòng): SEEK_SET 移到文件頭; SEEK_END 移到文件尾; SEEK_CUR 移到當(dāng)前位置(不動(dòng))
offset為精調(diào):確定了whence之后, 再移動(dòng)offset個(gè)位置
臨時(shí)文件
臨時(shí)文件的兩個(gè)特殊需求:1.文件名要唯一 2.不需要時(shí)最好能自己刪除
char *tmpnam(char *ptr):
產(chǎn)生唯一的"路徑/文件名"形式的字符串,傳入的參數(shù)可以為NULL,或者長(zhǎng)度不小于L_tmpnam的字符數(shù)組
FILE *tmpfile()
自動(dòng)生成文件名并創(chuàng)建臨時(shí)文件, 臨時(shí)文件在關(guān)閉或程序退出時(shí)自動(dòng)刪除
如果是一次性讀寫可以直接調(diào)用tmpfile, 如果需要重復(fù)讀寫可以用tmpnam生成文件名然后手動(dòng)創(chuàng)建和刪除文件
int main(){
printf("just test: %s\n",tmpnam(NULL));
char name[L_tmpnam];
tmpnam(name);
printf("name: %s\n",name);
char buf[1024];
FILE *fp;
if((fp=tmpfile()) == NULL){
printf("tmpfile error");
exit(1);
}
fputs("one line\n",fp);
rewind(fp);
fgets(buf,1024,fp);
printf("%s",buf);
return 0;
}