文件打開
open函數 ?? ?
#include <fcntl.h>
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
功能:
? ?打開或創建文件
? ?
參數:
? @pathname ?//打開的文件名
? @flags ? ? //操作的標志
? ? ? ? ? ? ?
?? ??? ??? ? //必選
?? ??? ??? ? O_RDONLY ?//只讀
?? ??? ??? ? O_WRONLY ?//只寫?
?? ??? ??? ? O_RDWR ? ?//讀寫?
?? ??? ??? ??
?? ??? ??? ?//附加
?? ??? ??? ?O_APPEND ?//追加?
?? ??? ??? ?O_CREAT ? //文件不存在 創建?
?? ??? ??? ?O_TRUNC ? //文件存在 ?截短為0?
? @mode ? ? 一般不用
? ? ? ? ? ? 當flags中使用了 O_CREAT 時,需要指定 mode ??
?? ??? ??? ?mode 0777
? ? ? ? ? ? ? ? ?0666
? ? ? ? ? ? ? ? ?0444 ?? ??? ??? ??? ??
返回值:
? 成功 文件描述符
? 失敗 -1 && errno會被設置?
??
??
fopen ? ? ? ? ? ? open
r? ? ? ? ? ? ? ? ?O_RDONLY?
r+ ? ? ? ? ? ? ? O_RDWR
w ? ? ? ? ? ? ? ?O_WRONLY|O_CREAT|O_TRUNC?
w+ ? ? ? ? ? ? ?O_RDWR|O_CREAT|O_TRUNC
a ? ? ? ? ? ? ? ?O_WRONLY|O_APPEND|O_CREAT
a+ ? ? ? ? ? ? ?O_RDWR |O_APPEND|O_CREAT
FILE * fopen(const char *pathname,const char *mode)
{
? ?...
? ?if (strcmp("r",mode))
? ? ? ?open(pathname,O_RDONLY);
}
文件創建好后的權限:
? a.指定的mode?
? b.umask ?(掩碼) //二進制位 --- 遮住?
? 最終文件的權限 = ~umask & mode
??
? 0 ?7 ? 7 ? 7?
? ? 111 111 111 ?mode
? 0 000 000 010
? ? 111 111 101 ~umask?
?? ?------------
?? ?111 111 101?
?? ? 7 ?7 ? 5
?? ?
?? ??? ??? ??? ??? ??? ?
庫函數 和 系統調用 ?? ??? ?
close?關閉:
int close(int fd);
功能:
? ?關閉文件描述符
? ?以便 再次使用?
參數:
? @fd ?要關閉的文件描述符
返回值:
? 成功 0
? 失敗 -1?
??
文件描述符:
1.非負整型數值?
2.分配原則
? 最小未使用 ??
3.范圍?
? 0~1023?
??
??
?
ssize_t ?read(int fd, ? ? ?void *buf, size_t count);
#include <unistd.h>
功能:?
? ? 從fd中讀數據 ,存到 buf中?
參數:
? ?@fd 要讀取的文件?
? ?@buf 存放讀取到的數據的 內存空間?
? ?@count 一次要讀取的數量(字節)
返回值:
? ?成功 表示成功讀到的字節數?
? ?失敗 -1 && errno?
? ?
ssize_t write(int fd,const void *buf, size_t count);
#include <unistd.h>
功能:?
? ? 把buf中 寫到fd中?
參數:
? ?@fd ? ?要寫入的文件?
? ?@buf ? 存放數據的 內存空間?
? ?@count 一次要寫入的數量(字節)
返回值:
? ?成功 表示成功寫入的字節數?
? ?失敗 -1 && errno?
緩存的設計
緩存 設計的目的提高效率 ?
本質上來說 ---緩存其實就是一塊內存空間?
行緩沖:
1k, terminal,主要用于人機交互stdout
?? ?
?? ?緩存區滿或者遇到\n刷新?? ?1024
?? ??? ??? ??? ?行緩存多是關于終端的一些操作
?? ??? ??? ??? ?1.遇到\n刷新
?? ??? ??? ??? ?2.緩存區滿刷新
?? ??? ??? ??? ?3.程序結束刷新
?? ??? ??? ??? ?4.fflush刷新 ?fflush(stdout);
?? ??? ??? ??? ?
全緩沖
4k,主要用于文件的讀寫
?? ?緩存區滿刷新緩存區 4096
?? ??? ??? ?對普通文件進行標準IO操作,建立
?? ??? ??? ?的緩存一般為全緩存
?? ??? ??? ?刷新條件:
?? ??? ??? ??? ?1.緩存區滿刷新
?? ??? ??? ??? ?2.程序結束刷新
?? ??? ??? ??? ?3.fflush來刷新 ?fflush(fp);
無緩沖
0k ?主要用于出錯處理信息的輸出 stderr?
?? ?不對數據緩存直接刷新
?? ?printf();==>>stdout?
?? ?fprintf(strerr,"fopen error %s",filename);
?? ??? ??? ??? ?界面交互?? ?出錯處理
使用gdb查看,FILE結構體,或使用寫入數據測試緩沖區。
緩沖區的大小是可以設置
linux下緩存設計:
交互 --- 行緩存?
文件 --- 全緩存?
出錯 --- 不緩存?
./a.out < main.c ? //< 表示輸入重定向?
./a.out > main.c ? //> 表示輸出重定向?
fread/fwrite //二進制讀寫函數 按對象讀寫
#include <stdio.h>
size_t ?fread( ? ? ?void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:
? ? ?二進制流的讀/寫
參數:
? ?@ptr ? 表示存放數據的空間的地址?
? ?@size ?要操作的單個元素(對象)的大小
? ?@nmemb 要操作的元素(對象)的個數?
? ?@stream 要操作的文件?
返回值:
? ?成功 返回的是 成功操作到的對象的個數?
? ?失敗 0
? ? ?到達文件結尾 返回 0
?? ??
應用:
? ?主要 應用在 文件中 有固定格式的 ?場景?
? ?
? ?
? ?
??
eg:
? ?將3個學生的信息,寫到文件中?之后,從文件中讀出學生信息,打印?
#include<stdio.h>
struct student
{char name[10];int sno;float score;
};int main(int argc, const char *argv[])
{FILE* fp = fopen(argv[1],"r+");if(argc!=2){printf("Usage:%s<filename>",argv[0]);return -1;}if(fp==NULL){perror("fail open");return -1;}struct student s[3]={"tom",110,99.7,"henry",111,99.8,"jery",112,99.2};fwrite(s,sizeof(struct student ),3,fp);rewind(fp);struct student s1[3];fread(s1,sizeof(struct student ),3,fp);int i=0;for(i=0;i<3;i++){printf("%s\n",s[i].name);printf("%d\n",s[i].sno);printf("%f\n",s[i].score);}fclose(fp);return 0;
}
? ?
? ?
文件偏移量:
? ?rewind
? ?int ?fseek(FILE* stream,long offset,int whence);
? ?功能:
? ? ? ?定位文件?
? ?參數:
? ? ? @stream ?表示要操作文件?
?? ? ?@offset ?表示文件偏移量?
?? ? ?@whence ?定位的參考點?
?? ? ? ? ? ? ? SEEK_SET //相對于文件開頭的?
?? ??? ??? ? ? ? ?offset >=0?
?? ??? ??? ? ? SEEK_CUR //相對于當前位置
?? ??? ??? ? ? ? ?offset>=0
?? ??? ??? ??? ? ?offset<0 ? //不能超過這個文件開頭
?? ??? ??? ? ? SEEK_END //相對于文件末尾?
?? ??? ??? ? ? ? ?offset < 0 ?//不能超過這個文件開頭
?? ??? ??? ? ? ? ?offset >= 0 //可以 ?--- 創建 空洞 文件
? ?返回值:
? ? ? 成功 0
?? ? ?失敗 -1
?? ? ?
?? ? ? ? ? ?? ??? ??? ??? ? ?
?? ? fseek(fp,100,SEEK_SET);//
?? ? fseek(fp,0,SEEK_SET);//定位到開頭?
?? ? fseek(fp,0,SEEK_END);//定位到末尾
?? ??
?? ? 創建空洞文件:?
?? ? 1.做偏移?
?? ? 2.寫操作?
#include<stdio.h>
int main(int argc, const char *argv[])
{if(argc != 3){printf("Usage:%s<filename><filename>\n",argv[0]);return -1;}FILE *fp1=fopen(argv[1],"r+");fseek(fp1,0,SEEK_END);long len = ftell(fp1);fseek(fp1,0,SEEK_SET);FILE *fp_h = fopen(argv[2],"w+");if(fseek(fp_h,len-1,SEEK_END)!=0){perror("fseek fail");return -1;}fputc('\0',fp_h);fseek(fp_h,0,SEEK_SET);char buf[100];//char buf[len];//ret=fread(buf,sizeof(buf),1,fp1);int ret;while(ret=fread(buf,sizeof(char),sizeof(buf),fp1)){fwrite(buf,sizeof(char),ret,fp_h);}fclose(fp1);fclose(fp_h);return 0;
}
?? ??
?? ? //空洞文件中的數據 ,都是0
?? ??
? ?long ftell(FILE*stream);
? ?功能:
? ? ? ?獲得當前文件的偏移量?
? ?void rewind(FILE*stream);
? ?功能:
? ? ? ?將文件偏移量設置到文件開頭?
?? ? ??
?? ? ??
? 獲得某個文件的大小:
? 1. fseek(fp,0,SEEK_END);//定位到末尾
? 2. long len =ftell(fp);?
??
?
練習:
? ?cp ??
#include<stdio.h>
int main(int argc, const char *argv[])
{if(argc!=3){printf("Usage:%s<filename><filename>",argv[0]);}FILE* fp = fopen(argv[1],"r+");FILE* fp1 = fopen(argv[2],"r+");char buf[1000];int ret;while(ret= fread(buf,sizeof(char),1000,fp)){fwrite(buf,sizeof(char),ret,fp1);}fclose(fp);fclose(fp1); return 0;
}
? ??
? ?
? ?
eg:
? ?1.統計文件中英文字符出現的次數?
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc, const char *argv[])
{if(argc!=2){printf("Usage:%s<filename>",argv[0]);return -1;}if(argv[1]==NULL){perror("fail open");return -1;}int fd = open(argv[1],O_RDONLY);unsigned char ch;int cnt[26]={0};while(read(fd,&ch,1)!=0){if(ch>='a'&&ch<='z'){cnt[ch-'a']++;}else if(ch>='A'&&ch<='Z'){cnt[ch-'A']++;}}int i;for(i=0;i<26;i++){printf("%c:%d\n",i+'a',cnt[i]);}return 0;
}
? ?2.
? ?bmp圖片:
? ?[54頭信息]
? ?[圖像信息] //bmp圖像信息 --- 原始圖像?
#include<stdio.h>
//-/a.out 0.bmp 2.bmp 3.bmp
int main(int argc, const char *argv[])
{if(argc != 4){printf("usage: %s <src0.bnp> <src2.bnp> <dest.bnp>\n",argv[0]);return -1;}FILE *fp1 = fopen(argv[1],"r");FILE *fp2 = fopen(argv[2],"r");FILE *fp3 = fopen(argv[3],"w");if (fp1 == NULL || fp2 == NULL || fp3 == NULL){perror("fopen fail");return -1;}unsigned char head1[54];//unsigned char head2[54];//unsigned char body1[600*800*3];//unsigned char body2[600*800*3];//fread(head1, sizeof(unsigned char),54,fp1);fread(body1,sizeof(unsigned char),600*800*3,fp1);fread(head2,sizeof(unsigned char),54,fp2);fread(body2,sizeof(unsigned char),600*800*3,fp2);int i=0;for(i=0;i<600*800*3;i++){if (!(body1[i] == 255&&body1[i+1]==255&&body1[i+2]==255)){body2[i] =body1[i];body2[i+1] = body1[i+1];body2[i+2] =body1[i+2];}}fwrite(head2,sizeof(char),54,fp3);fwrite(body2,sizeof(char),600*800*3,fp3);fclose(fp1);fclose(fp2);fclose(fp3);return 0;
}
運行結果:
? ?
1.bmp
2.bmp
t.bmp