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