始的敲代碼生活--Linux應(yīng)用軟件(文件操作基礎(chǔ)1))
一、文件基礎(chǔ)概念1. 文件程序變量、數(shù)組、數(shù)據(jù)結(jié)構(gòu)存放在內(nèi)存文件存儲(chǔ)在外存硬盤(pán)。對(duì)比項(xiàng)內(nèi)存外存(硬盤(pán)/文件)讀寫(xiě)速度快比內(nèi)存慢數(shù)據(jù)保持程序執(zhí)行結(jié)束、掉電數(shù)據(jù)丟失掉電數(shù)據(jù)不丟失空間/價(jià)格空間小價(jià)格昂貴空間大相對(duì)內(nèi)存價(jià)格便宜文件用于長(zhǎng)期保存掉電不丟失的數(shù)據(jù)。Linux一切皆文件硬件也通過(guò)文件接口給應(yīng)用層操作。2. Linux下文件類(lèi)型ls -l 文件名可以查看文件信息。示例-rwxrwxr-x 1 linux linux 19856 Aug 14 19:20 a.outLinux一共7種文件類(lèi)型標(biāo)志類(lèi)型說(shuō)明示例bblock 塊設(shè)備文件存儲(chǔ)類(lèi)文件硬盤(pán)ccharacter 字符設(shè)備文件字符設(shè)備鼠標(biāo)、鍵盤(pán)、顯示器ddirectory 目錄文件文件夾普通文件夾-regular 普通文件普通文件main.c、txt、jpg、可執(zhí)行程序llink 軟連接文件快捷方式符號(hào)鏈接—ssocket 套接字文件網(wǎng)絡(luò)編程—ppipe 管道文件進(jìn)程間通信—普通文件分為二進(jìn)制文件存儲(chǔ)二進(jìn)制01序列如a.out、png、mp3ASCII文本文件存儲(chǔ)字符如.c、.h、.txt可用cat、od -c查看3. Linux下文件操作方法標(biāo)準(zhǔn)IOC庫(kù)函數(shù)#include stdio.h例如printf、scanf文件IO系統(tǒng)調(diào)用由Linux內(nèi)核提供接口文件操作通用流程打開(kāi)文件讀寫(xiě)文件關(guān)閉文件man手冊(cè)使用Linux命令man 1 ls系統(tǒng)調(diào)用man 2 open庫(kù)函數(shù)man 3 fopen二、標(biāo)準(zhǔn)IO文件流讀寫(xiě)過(guò)程中的字節(jié)流標(biāo)準(zhǔn)IO操作面向FILE*文件流指針。系統(tǒng)默認(rèn)預(yù)先打開(kāi)三個(gè)流文件流對(duì)應(yīng)設(shè)備說(shuō)明stdin鍵盤(pán)標(biāo)準(zhǔn)輸入流stdout終端顯示屏標(biāo)準(zhǔn)輸出流stderr終端顯示屏標(biāo)準(zhǔn)錯(cuò)誤流1. fopen 打開(kāi)文件FILE *fopen(const char *pathname, const char *mode);參數(shù)pathname文件路徑名稱mode打開(kāi)模式mode含義r只讀文件必須存在r讀寫(xiě)文件必須存在w只寫(xiě)不存在創(chuàng)建存在清空原有內(nèi)容w讀寫(xiě)不存在創(chuàng)建存在清空原有內(nèi)容a追加只寫(xiě)不存在創(chuàng)建寫(xiě)在文件末尾a讀寫(xiě)讀從開(kāi)頭寫(xiě)向末尾追加返回成功返回FILE*失敗返回NULL。2. fclose 關(guān)閉文件int fclose(FILE *stream);成功返回0失敗返回EOF(-1)。注意文件用完必須關(guān)閉否則產(chǎn)生文件描述符泄露。3. fputc 寫(xiě)入單個(gè)字符int fputc(int c, FILE *stream);putchar(a)等價(jià)于fputc(a,stdout)。 返回成功字符失敗返回EOF。4. fgetc 讀取單個(gè)字符int fgetc(FILE *stream);讀到文件末尾/出錯(cuò)返回EOF。fgetcfputc實(shí)現(xiàn)文件拷貝命令行傳參argc/argv#include stdio.h int main(int argc, const char *argv[]) { if (argc 3) { printf(Usage: ./a.out srcfile dstfile\n); return -1; } FILE *fpsrc fopen(argv[1], r); FILE *fpdst fopen(argv[2], w); if (NULL fpsrc || NULL fpdst) { printf(fopen error\n); return -1; } int ret 0; while (1) { ret fgetc(fpsrc); if (EOF ret) { break; } fputc(ret, fpdst); } fclose(fpsrc); fclose(fpdst); return 0; }5. fputs 寫(xiě)字符串int fputs(const char *s, FILE *stream);將字符串寫(xiě)入文件不會(huì)寫(xiě)入\0成功返回0失敗返回EOF。6. fgets 讀取一行char *fgets(char *s, int size, FILE *stream);最多讀取size?1字節(jié)末尾自動(dòng)補(bǔ)\0讀到換行會(huì)保存換行符。gets不安全不推薦使用scanf遇到空格、tab、換行停止讀取。fgetsfputs實(shí)現(xiàn)文件拷貝函數(shù)int file_cp(const char *srcfile, const char *dstfile) { FILE *fpsrc fopen(srcfile, r); FILE *fpdst fopen(dstfile, w); if (NULL fpsrc || NULL fpdst) { printf(fopen error\n); return -1; } char buff[1024] {0}; while (NULL ! fgets(buff, sizeof(buff), fpsrc)) { fputs(buff, fpdst); } fclose(fpsrc); fclose(fpdst); return 0; }fgets/fputs適合文本文件不適合二進(jìn)制文件。7. fwrite 塊寫(xiě)size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);向文件寫(xiě)入nmemb個(gè)、每個(gè)大小size字節(jié)的數(shù)據(jù)單元返回成功寫(xiě)入的單元個(gè)數(shù)。8. fread 塊讀size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);從文件讀取nmemb個(gè)單元到ptr內(nèi)存返回實(shí)際讀到的單元數(shù)量。9. 文件流定位fseek重定位讀寫(xiě)位置int fseek(FILE *stream, long offset, int whence);SEEK_SET從文件起始位置偏移SEEK_CUR從當(dāng)前位置偏移SEEK_END從文件末尾偏移ftell獲取當(dāng)前距離文件開(kāi)頭字節(jié)偏移long ftell(FILE *stream);rewind將文件流直接回到文件開(kāi)頭void rewind(FILE *stream);獲取文件大小示例fseek(fp, 0, SEEK_END); len ftell(fp); rewind(fp);三、時(shí)間相關(guān)函數(shù)頭文件#include time.h1. time 獲取時(shí)間戳秒數(shù)time_t time(time_t *tloc);獲取從1970?01?01 00:00:00到當(dāng)前的秒數(shù)。2. ctime 將時(shí)間戳轉(zhuǎn)為字符串時(shí)間char *ctime(const time_t *timep);3. localtime 將時(shí)間戳轉(zhuǎn)為tm日歷結(jié)構(gòu)體struct tm *localtime(const time_t *timep);struct tm結(jié)構(gòu)體成員struct tm { int tm_sec; /* 秒 0?60 */ int tm_min; /* 分 0?59 */ int tm_hour; /* 時(shí) 0?23 */ int tm_mday; /* 日期 1?31 */ int tm_mon; /* 月份 0?11 */ int tm_year; /* 年份實(shí)際tm_year1900 */ int tm_wday; /* 星期 0?6周日0 */ int tm_yday; /* 一年中的第幾天 */ int tm_isdst; /* 夏令時(shí) */ };