上一篇總結了文件I/O的系統調用,今天來總結下標準I/O庫在工做幾年常常使用的函數。數組
標準I/O庫(#include<stdio.h>)實際就是封裝了系統調用;這樣作的主要目的是減小對系統調用的調用,從而提升效率。ide
一、流和FILE對象函數
文件I/O操做的的文件描述符,而標準I/O庫操做的是流即就是FILE對象。當打開一個流時,返回一個FILE對象。ui
二、標準輸入、標準輸出、標準錯誤spa
對應文件I/O的文件描述符文件爲:0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO)orm
對應標準I/O庫的流爲:stdin、stdout、stderr;對象
三、標準I/O提供三種緩衝(減小對系統調用的調用)路由
int setbuf(FILE *stream,char *buf );/*buf =null 關閉緩衝,buf長度=BUFSIZE設置緩衝區*/ int setvbuf(FILE *stream,char *buf,int mode,size_t size);/*mode :_IOFBF 全緩衝;_IOLBF行緩衝;_IONBF不帶緩衝。長度爲size 的buf,若是buf=NULL,則爲系統默認大小。*/ int fflush(FILE*fp);/*強制刷新一個流,用於刷新緩衝區*/
1) 全緩衝:當不涉及到交互式設備時,則爲全緩衝。開發
2) 行緩衝:終端設備通常是行緩衝。有時不須要緩衝區,好比以前例子裏,須要實時打印printf,因此要講其設置成不帶緩衝: rem
setvbuf(stdout,NULL,_IONBF,0)
3) 不帶緩衝:標準出錯就是不帶緩衝,當出現錯誤的時候會當即輸出。
四、 打開和關閉流
FILE *fopen(const char *path,const char *mode); FILE *fdopen(int fd,const char *mode); FILE *freopen(const char *path,const char *mode,FILE *stream);
三個函數都是打開一個流,fopen:打開一個指定的流;fdopen:流和一個文件描述符結合;freopen:在一個指定的流上打開一個指定的文件,已打開則關閉、已定向則消除。
mode:r讀、r+讀寫、w寫、w+讀寫、a在文件尾部寫、a+在文件尾部讀和寫。
int fclose(FILE *stream);/*關閉一個流*/
五、讀和寫流
讀和寫流分爲三種:每次一個字符的I/O;每次一行的I/O;直接I/O(二進制I/O)按字節操做。
1) 字符I/O
讀函數:
int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void);/*getc(stdin)*/
由於要判斷出錯或者是否是到了流的末端(EOF = -1),因此返回值都是整型。
用函數:int ferror(FILE *fP)/*未出錯返回0*//int feof(FILE *fp)/*返回0表示文件未結束*/
寫函數:
int putc(int c,FILE *fp); int fputc(int c,FILE *fp); int putchar(int c);/*putc(c,stdout)*/
2) 行I/O
讀函數:
char *fgets(char *buf,int n,FILE *fp);/*讀到下一個換行符若是buf夠大,若是buf沒有一行大,返回一個不完整的行,下次繼續讀改行*/ char *gets(char *buf);/*從stdin讀*/
寫函數:
char fputs(char *buf,FILE *fp); char puts(char *buf);/*寫到stdout*/
3) 二進制I/O
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream ); size_t fwite(const void*ptr,size_t size,size_t nmemb,FILE *stream);
/*size指定ptr長度,nmemb指定讀或者寫幾個size長度的ptr*/
工做中常常從flash讀出設備的鏡像:
/*read boot & image*/ cs_status cs_build_image() { cs_uint32 offset = 0; int ret = 0; FILE * bootfp = NULL; FILE * imgfp = NULL; ULONG lByte = 0; /*讀取文件時的單元長度*/ UCHAR ucBuffer[1024] = {0};/*用來存儲讀出來鏡像單元*/ ULONG ulImageLen = 0; /*記錄文件的整體長度*/ UCHAR uc8124imgName[48] = {0}; /*local file name*/ UCHAR uc8124stage2ImgName[48] = {0}; /*local file name*/ UCHAR head = 64; sprintf( uc8124stage2ImgName, "/ram0/%s", "stage2" ); if( NULL == ( bootfp = fopen( uc8124stage2ImgName, "wb+" ) ) ) { printf( "open to cs8124_img file!\r\n" ); return ERROR; } ret = GenHwSysFlashload8124Stage2Image(bootfp); if( OK != ret ) { printf( "read 8124Stage2Image from flash error! \r\n" ); return ERROR; } g_uc8124stage2Image = (cs_uint8*)malloc(sizeof(cs_uint8) * TEST_MAX_OLT_LOADER_IMAGE ); if(g_uc8124stage2Image == NULL){ printf("malloc g_uc8124stage2Image error\n"); } memset(g_uc8124stage2Image, 0, TEST_MAX_OLT_LOADER_IMAGE); fseek( bootfp, 0, SEEK_SET ); while( 0 < ( lByte = fread( ucBuffer, 1, 1024, bootfp ) ) ) { ulImageLen += (lByte-head); /*寫在本地文件操做*/ memcpy( g_uc8124stage2Image + offset, ucBuffer+head , lByte-head ); offset += lByte-head; memset( ucBuffer, 0 , sizeof( ucBuffer ) ); head = 0; } printf("[%s%d ] g_uc8124stage2Image:%d\n",__FILE__,__LINE__,ulImageLen); g_ucStage2ImageLen = ulImageLen; if(TEST_MAX_OLT_LOADER_IMAGE < ulImageLen){ return ERROR; } fclose( bootfp); ret = remove( uc8124stage2ImgName ); if( OK != ret ) { printf( " 8124stage2Image error! \r\n" ); return ERROR; } /*get cs8124 image(firmware)*/ sprintf( uc8124imgName, "/ram0/%s", "imgenew" ); if( NULL == ( imgfp = fopen( uc8124imgName, "wb+" ) ) ) { printf( "Fail to create cs8124_img file!\r\n" ); return ERROR; } ret = GenHwSysFlashload8124Image(imgfp); if( OK != ret ) { printf( "read 8124Image from flash error! \r\n" ); return ERROR; } g_ucpOltImage = (cs_uint8*)malloc(sizeof(cs_uint8) * TEST_MAX_OLT_IMAGE ); if(g_ucpOltImage == NULL){ printf("malloc g_ucpOltImage error\n"); } memset(g_ucpOltImage, 0, TEST_MAX_OLT_IMAGE); fseek( imgfp, 0, SEEK_SET ); lByte = 0; ulImageLen = 0; offset = 0; head = 64; memset( ucBuffer, 0 , sizeof( ucBuffer ) ); while( 0 < ( lByte = fread( ucBuffer, 1, 1024, imgfp ) ) ) { ulImageLen += (lByte-head); /*寫在本地文件操做*/ memcpy( g_ucpOltImage + offset, ucBuffer+head , lByte-head ); offset += lByte-head; memset( ucBuffer, 0 , sizeof( ucBuffer ) ); head = 0; } printf("[%s%d ] g_ucpOltImage len:%d\n",__FILE__,__LINE__,ulImageLen); g_ucOltImageLen = ulImageLen; if(TEST_MAX_OLT_IMAGE < ulImageLen){ return ERROR; } fclose( imgfp); ret = remove( uc8124imgName ); if( OK != ret ) { printf( " uc8124imgName error! \r\n" ); return ERROR; } }
六、 定位流函數
int fseek(FILE *fp,long offset,int whence);/*和文件I/Olseek函數相似,whence相同:SEEK_SET從文件起始開始,SEEK_CUR從文件當前開始,SEEK_END從文件末端開始*/
七、 格式化I/O
格式化輸出函數:
int printf(const char *format,….); int fprintf(FILE *fp,const char *format,….); int sprintf(char *buf,const char *format,…); int snprintf(char *buf,size_t n,const char *format,…);
/*printf將格式化數據寫到標準輸出,fprintf寫到指定的流,sprintf將格式化的字符串送到數組buf中。snprintf指定buf長度n*/
在工做中常常使用snprintf,好比剛剛開發完靜態路由是用到的:
格式化輸入函數(和輸出相似):
int scanf(const *format,…); int fscanf(FILE *fp,const *format,..); int sscanf(const char *buf,const char *format,…);
八、建立臨時文件函數
FILE *tmpfile(void);/*建立一個臨時二進制文件wb+,在關閉該文件或程序結束時將自動刪除這種文件*/