是很多人學(xué)C語言接觸的第一個頭文件,顧名思義,stdio就是"標(biāo)準(zhǔn)輸入輸出",其中聲明了一組關(guān)于輸入輸出的類型,宏和函數(shù),其中就包括了打印著名的"hello,world!"的printf(),但是,這并不意味著這個頭文件就很簡單,相反,這個頭文件是C標(biāo)準(zhǔn)庫里唯二包羅萬象的一個庫(另一個是)。好,讓我們從頭審視一下這個頭文件
概念
文件描述符file descriptor
似于Windows系統(tǒng)的文件句柄,Unix/Linux系統(tǒng)用來描述文件的一個正整數(shù),OS負(fù)責(zé)分發(fā)文件描述符給程序員,并把關(guān)于這個文件細(xì)節(jié)的控制信息存儲在自己的專用內(nèi)存中,這些信息由OS維護,不需要程序員費心思。
文本VS二進制
在ANSI C編程可以指定文件的打開方式是按照"二進制"還是"文本"方式,如果在Unix系統(tǒng)這種不區(qū)分"文本"和"二進制"的系統(tǒng)中,可以省略這種指定,但是畢竟很多OS還是對這兩種文件類型加以區(qū)分的,所以最好還是進行明確的指定以便實現(xiàn)可移植性。
流stream
ANSI C將對文件讀寫看作是數(shù)據(jù)的流出和流入,而隱藏了文件物理存儲介質(zhì)的不同,即不論這個文件是存儲的磁盤,內(nèi)存,F(xiàn)LASH還是其他地方,在程序員看來都只是一個文件,而對一個文件的處理都是數(shù)據(jù)的流入和流出。打開一個文件會把一個物理介質(zhì)上的文件連接到流的一端。通過流來對實際的文件進行讀寫,關(guān)閉一個文件會把一個物理介質(zhì)上的文件和流斷開。
ANSI C規(guī)定了兩種流——文本流和二進制流,前者將數(shù)據(jù)看作字符,即201609是6個字符'2','0','1','6','0','9',占6byte,而在二進制流中,這就是int,占4byte。此外,文本流也會將'\n'轉(zhuǎn)換成'回車CR'和'換行LR'兩個字符,而二進制流不會。從這兩個角度看,二進制流的流動速度比文本流更快,也更省存儲空間
數(shù)據(jù)類型
size_t
FILE
FILE是ANSIC中用來保存文件信息的一個結(jié)構(gòu)體,使用ANSI C編程時打開一個文件就是得到的就是一個FILE*(文件指針),如果是使用UNix/Linux系統(tǒng)下的編譯器,那么任何通過對FILE*對文件的操作底層都是使用文件描述符來實現(xiàn)的,當(dāng)然其他平臺的具體實現(xiàn)還可能不一樣
//gcc 4.9.2中對FILE類型的聲明typedef struct _IO_FILE FILE;struct _IO_FILE { int _flags; char* _IO_read_ptr; char* _IO_read_end; char* _IO_read_base; char* _IO_write_base; char* _IO_write_ptr; char* _IO_write_end; char* _IO_buf_base; char* _IO_buf_end; char *_IO_save_base; char *_IO_backup_base; char *_IO_save_end; struct _IO_marker *_markers; struct _IO_FILE *_chain; int _fileno; int _flags2; __off_t _old_offset; unsigned short _cur_column; signed char _vtable_offset; char _shortbuf[1]; _IO_lock_t *_lock;# 293 "/usr/include/libio.h" 3 4 __off64_t _offset;# 302 "/usr/include/libio.h" 3 4 void *__pad1; void *__pad2; void *__pad3; void *__pad4; size_t __pad5; int _mode; char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];};typedef struct _IO_FILE _IO_FILE;
fpos_t
fpos_t可以唯一指定文件中的每個位置所需的所有信息,實際上是一個整型變量,用來記錄當(dāng)前讀寫位置距離文件開頭的byte數(shù),很多文件讀寫函數(shù)在讀寫一次后都會改寫這個變量的值
宏
NULL
_IOFBF, _IOLBF, _IONBF
這三個宏展開為具有不同值的常量表達式,是個作為函數(shù)setvbuf的第三個arg
BUFSIZ
展開為一個整型常量表達式,只setbuf()緩沖池的大小
EOF
End of File,展開為一個負(fù)的整型常量表達式,表示一個流結(jié)束了
FOPEN_MAX
展開為一個整型常量表達式,表示當(dāng)前環(huán)境下可以同時打開文件數(shù)目的最大數(shù)目
FILENAME_MAX
展開為一個整型常量表達式,表示用來保存文件名的char數(shù)組的大小,即文件名的最大長度
L_tmpnam
展開為一個整型常量表達式,表示用來保存tmpnam()生成的臨時文件名串的char數(shù)組的大小
SEEK_CUR, SEEK_END, SEEK_SET
展開為不同值的整型常量表達式,用作fseek()函數(shù)的arg
TMP_MAX
展開為一個整型常量表達式,表示tmpnam()可以聲場的單獨文件名的最小數(shù)目
stderr, stdin, stdout
展開為一個"FILE*"類型的表達式,分別指向標(biāo)準(zhǔn)錯誤流,標(biāo)準(zhǔn)輸入流,標(biāo)準(zhǔn)輸出流,Unix/Linux系統(tǒng)中這三個流默認(rèn)分別是顯示器,鍵盤,顯示器
函數(shù)
文件訪問
remove()
/*功能:導(dǎo)致一個文件再也不能通過它的文件名filename訪問,除非重新創(chuàng)建該文件返回值:成功返回0,否則返回非0*/int remove(const char* filename);
rename()
/*功能:把名字為oldname的文件改名為newname返回值:*/int rename(const char* oldname,const char* newname);
tmpfile()
/*功能:創(chuàng)建一個臨時二進制文件,文件被關(guān)閉就會被移除返回值:成功返回FILE*,否則返回void\*FILE* tmpfile(void);
tmpnam()
//生成一個有效的文件名char* tmpnam(char* s);
fclose()
/*功能:將stream指向的流被清空,并且和流相關(guān)聯(lián)的文件被關(guān)閉,流中任何未寫出的緩沖數(shù)據(jù)都傳遞到環(huán)境并寫入文件,任何未讀的都被丟棄。返回值:成功返回0,否則返回EOF*/int fclose(FILE* stream);
fflush()
/*功能:清空stream指向的流,未寫入文件的會被寫入,未讀的丟棄參數(shù):流stream返回值:*/int fflush(FILE* stream);
fopen()
/*功能:打開以串filename為名的文件,并把這個文件和一個流相連參數(shù):文件名字符串filename,打開方式mode如下:r 只讀w 清空寫a 追加寫b 放在rwa之后,表示"以二進制方式"+ 放在rwa之后,表示"文件不存在就創(chuàng)建"返回值:成功返回FILE*,失敗返回void**/FILE* fopen(const char* filename,const char* mode);
freopen()
/*功能:打開路徑為filename指向的串文件,并把這個文件和流stream相連返回值:成功返回stream的值,否則返回void**/FILE* freopen(const char* filename, const char* mode,FILE* stream);
setvbuf()
/*功能:指定流stream緩沖的方式,只能在流和一個文件關(guān)聯(lián)后,但還沒有對流進行其他操作之前使用參數(shù):mode指定流緩沖的方式,_IOFBF表示完全緩沖,即緩沖區(qū)滿才對文件操作,_IOLBF表示輸入/輸出行緩沖,即緩沖區(qū)中遇到換行就對文件進行操作,_IONBF表示輸入/輸出不換沖,如果buf不是void*,則可以用它指向的數(shù)組來代替setvbuf()自動分配的緩沖區(qū),size指定了數(shù)組的大小。返回值:成功返回0,否則返回非0; */int setvbuf(FILE* stream, char* buf, int mode, size_t size);
setbuf()
/* 功能:如果buf不是void*,相當(dāng)于mode為_IOFBF,size為BUFSIZd調(diào)用setvbuf(),如果哦buf是void*,相當(dāng)于mode為_IONBF調(diào)用setvbuf()返回值:無*/void setbuf(FILE* stream, char* buf);
格式化輸出輸出
fprintf()
/*功能:按照format指向的格式控制串把輸出寫入stream指向的流參數(shù):返回值:成功返回輸出項的數(shù)目,失敗返回EOF*/int fprintf(FILE* stream, const char* format,...);
fscanf()
/*功能:按照format指向的格式控制串,把后面的參數(shù)作為指向接收轉(zhuǎn)換后的輸入的對象的指針參數(shù):返回值:成功返回輸入項的數(shù)目,失敗返回EOF*/int fscanf(FILE* stream, const char* format, ...);
printf()
/*功能:相當(dāng)于fprintf(),只是把stdout作為stream參數(shù):返回值:成功返回輸出項的數(shù)目,否則返回負(fù)值*/int printf(const char* format, ...);
scanf()
/*功能:相當(dāng)于fsanf(),只是把stdin作為stream參數(shù):返回值:成功返回輸入項的數(shù)目,失敗返回EOF*/int scanf(const char* formant, ...);
sprintf()
/*功能:相當(dāng)于fprintf(),只是把本來寫入流stream的內(nèi)容改為寫入到數(shù)組s中參數(shù):返回值:成功寫入數(shù)組中字符的數(shù)目,不包括NUL*/int sprintf(char *s, const char* format, ...);
ssanf()
/*功能:相當(dāng)于fscanf(),只是把本來從流stream獲取的內(nèi)容改為從數(shù)組s獲取參數(shù):返回值:成功輸入項的數(shù)目,否則返回EOF*/int sscanf(const char* s, const char* format, ...);
vfprintf()
/*功能:相當(dāng)于fprintf(),只是把可變參數(shù)表用arg代替參數(shù):返回值:成功返回輸出項的數(shù)目,否則返回一個負(fù)數(shù)*/int vfprintf(FILE* stream, const char* format, va_list arg);
vprintf()
/*功能:相當(dāng)于printf(),只是把可變參數(shù)表用arg代替參數(shù):返回值:成功返回輸出項的數(shù)目,否則返回一個負(fù)數(shù)*/int vprintf(const char* format, va_list arg);
vsprintf()
/*功能:相當(dāng)于sprintf(),只是把可變參數(shù)用arg代替參數(shù):返回值:成功返回輸出項的數(shù)目,否則返回一個負(fù)數(shù)*/int vsprintf(char* s, const char* format, va_list arg);
字符輸出輸出
fgetc()
/*功能:從stream指向的輸入流中讀取下一個字符,并把它由unsigned char轉(zhuǎn)換為int參數(shù):返回值:成功返回讀取到的字符,否則返回EOF*/int fgetc(FILE* stream);
fgets()
/*功能:從stream指向的流中讀取字符,讀取字符的數(shù)目最多為n-1,因為至少還要給NUL留位置,然后將字符寫入到數(shù)組s中,如果敲入"123回車"存儲的是"123\0",這個函數(shù)會自動把輸入的'\n'變成'\0',這點和scanf()不同參數(shù):返回值:*/char* fgets(char* s, int n, FILE* stream);
fputc()
/*功能:把c字符寫入到stream指向的輸出流中的文件定位符指定的位置,并將位置指針移動一個參數(shù):返回值:*/int fputc(int c, FILE* stream);
fputs()
/*功能:把s串的有效字符寫入stream參數(shù):返回值:成功返回一個非負(fù)值,否則返回EOF*/int fputs(const char* s, FILE* stream);
getc()
/*功能:相當(dāng)于fgetc(),只是如果getc()作為一個宏實現(xiàn)時,可能會對stream進行多次進算,所以它的參數(shù)不能是有副作用的表達式參數(shù):返回值:*/int getc(FILE* stream);
getchar()
/*功能:相當(dāng)于fgetc(),只是從stream獲取改為從stdin獲取參數(shù):返回值:*/int getchar(void);
gets()
/*功能:有的資料說相當(dāng)于fgets(),只是從stream獲取改為從stdin獲取,直到遇到一個換行符,其實gets和fgets最大的區(qū)別就是不回進行輸入字符數(shù)目的限制,一旦用戶輸入的字符個數(shù)超過了接收buf的大小,就可能引發(fā)錯誤,所以不建議使用這個函數(shù)參數(shù):返回值:*/char* gets(char* s);
putc()
/*功能:相當(dāng)于fputc(),只是如果putc()作為一個宏實現(xiàn)時,可能會對stream進行多次暈眩,所以它的參數(shù)不能是有副作用的表達式參數(shù):返回值:*/int putc(int c, FILE* stream);
putchar()
/*功能:相當(dāng)于fputc(),只是輸出到stream改為輸出到stdout參數(shù):返回值:*/int putchar(int c);
puts()
/*功能:相當(dāng)于fputs(),只是輸出到stream改為輸出到stdout參數(shù):返回值:*/int puts(const char* s);
ungetc()
/*功能:把c字符退回到stream參數(shù):返回值:*/int ungetc(int c, FILE* stream);
直接輸入輸出
fread()
/*功能:從stream中讀取最多nmemb個元素到ptr指向的數(shù)組中參數(shù):返回值:成功返回讀取的元素的個數(shù)*/size_t fread(void *ptr, size_t size, size_t nmemb, FILE* stream);
fwrite()
/*功能:從ptr指向的數(shù)組中讀取最多nmemb個元素并將其寫到stream中參數(shù):返回值:*/size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);
文件定位函數(shù)
fgetpos()
/*功能:把stream中的定位符的當(dāng)前值存儲到pos指向的對象中參數(shù):返回值:*/int fgetpos(FILE* stream, fpos_t* pos);
fseek()
/*功能:為stream設(shè)置文件定位符參數(shù):offset表示以whence為基準(zhǔn)的偏移量,whence有三種值:SEEK_SET表示以文件開頭為基準(zhǔn),SEEK_CUR表示以當(dāng)前文件定位符位置為基準(zhǔn),SEEK_END表示以文件結(jié)尾為基準(zhǔn)返回值:成功返回0,否則返回非0*/int fseek(FILE* stream, long int offset, int whence);
fsetpos()
/*功能:根據(jù)pos指向的對象的值來設(shè)置stream中定位符的位置參數(shù):返回值:成功返回0,否則返回非0,并設(shè)置errno*/int fsetpos(FILE* stream, const fpos_t* pos);
ftell()
/*功能:獲得stream定位符的當(dāng)前值參數(shù):返回值:返回文件定位符當(dāng)前值,否則返回-1L,并設(shè)置errno*/long int ftell(FILE* stream);
rewind()
/*功能:把stream的文件定位符設(shè)置在文件的開始位置,等價于(void) fseek(stram, 0L,SEEK_SET)參數(shù):返回值:*/void rewind(FILE* stream);
錯誤處理
clearerr()
/*功能:清空stream指向的流文件結(jié)束符和錯誤指示符參數(shù):返回值:*/void clearerr(FILE* stream);
feof()
/*功能:測試stream的文件結(jié)束符參數(shù):返回值:如果stream設(shè)置了文件結(jié)束符返回一個非0*/int feof(FILE* stream);
ferror()
/*功能:測試stream指向的流的錯誤提示符參數(shù):返回值:如果stream設(shè)置了錯誤提示符返回非0*/int ferror(FILE* stream);
perror()
/*功能:把errno轉(zhuǎn)換成一個human-readable的信息參數(shù):返回值:*/void perror(const char* s);
?
評論