函數fwrite
功能
??C語言函數,向文件寫入一個數據塊??。
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
注意:這個函數以二進制形式對文件進行操作,不局限于文本文件
返回值:返回實際寫入的數據塊數目
(1)buffer:是一個指針,對fwrite來說,是要輸出數據的地址;
(2)size:要寫入內容的單字節數;
(3)count:要進行寫入size字節的數據項的個數;
(4)stream:目標文件指針;
(5)返回實際寫入的數據項個數count。
剛才編一個關于用C庫函數實現的文件復制操作的代碼時發生錯誤。錯誤的根本是想當然的以為fread函數的用法,對其理解不深刻。后來在網友幫助下才發現錯誤。
其實函數的用法可以通過Linux中的man來獲得幫助。
比如fread.在終端鍵入
- man?3?fread???
- NAME??
- ???????fread,?fwrite?-?binary?stream?input/output??
- ??
- SYNOPSIS??
- ???????#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);??
- ??
- DESCRIPTION??
- ???????The?function?fread()?reads?nmemb?elements?of?data,?each?size?bytes?long,?from?the?stream?pointed?to?by?stream,?storing?them?at?the?location?given?by?ptr.??
- ??
- ???????The??function??fwrite()??writes??nmemb?elements?of?data,?each?size?bytes?long,?to?the?stream?pointed?to?by?stream,?obtaining?them?from?the?location?given?by??
- ???????ptr.??
- ??
- ???????For?nonlocking?counterparts,?see?unlocked_stdio(3).??
- ??
- RETURN?VALUE??
- ???????On?success,?fread()?and?fwrite()?return?the?number?of?items?read?or?written.??This?number?equals?the?number?of?bytes?transferred?only?when?size?is?1.??If?an??
- ???????error?occurs,?or?the?end?of?the?file?is?reached,?the?return?value?is?a?short?item?count?(or?zero).??
- ??
- ???????fread()?does?not?distinguish?between?end-of-file?and?error,?and?callers?must?use?feof(3)?and?ferror(3)?to?determine?which?occurred.??
重點放在對返回值。
可以看出,如果調用成功的話,函數會返回讀到的元素個數。如果想返回實際讀取的字節數的話只有當size=1,也就是第二個參數size為1時。如果發生讀取錯誤的話,或者已經到達文件末尾,返回值是一個小的元素個數值或者是0.下面給出我的代碼,正確實現文件拷貝的代碼,以此分析。
- #include?<stdio.h>??
- ??
- #define?BUFFER_SIZE??1024??
- ??
- int?main(int?argc,?char?*argv[])??
- {??
- ????FILE?*from_fp,?*to_fp;??
- ????int?bytes_read,?bytes_write;??
- ????char?*ptr;??
- ????char?buffer[BUFFER_SIZE];??
- ??
- ????if(argc?!=?3)???????//參數包括源文件名與目標文件名??
- ????{??
- ????????printf("Input?failed!\n");??
- ????????return?1;??
- ????}??
- ??
- ????if(?(from_fp?=?fopen(argv[1],"r"))?==?NULL?)????//以只讀方式打開源文件名??
- ????{??
- ????????printf("File?is?not?exist\n");??
- ????????return?1;??
- ????}??
- ??????
- ????if((to_fp?=?fopen(argv[2],"w+"))?==?NULL)??????//打開第二個文件??
- ????{??
- ????????printf("Open?file?failed!\n");????
- ????????return?1;??
- ????}??
- ??
- ????while(bytes_read?=?fread(buffer,?1,?BUFFER_SIZE,?from_fp))??//讀取BUFFSIZE大小字節??
- ????{??
- ????????if(bytes_read?>?0)???????????//讀取有效數據??
- ????????{??
- ????????????ptr?=?buffer;??
- ????????????while(bytes_write?=?fwrite(ptr,?1,?bytes_read,?to_fp))??//寫數據到目標文件??
- ????????????{??
- ????????????????if(bytes_write?==?bytes_read)???????????//寫完??????
- ????????????????????break;??
- ????????????????else?if(bytes_write?>?0)?????????//未寫完??
- ????????????????{??
- ????????????????????ptr?+=?bytes_write;??
- ????????????????????bytes_read?-=?bytes_write;??
- ????????????????}??
- ????????????}??
- ????????????if(bytes_write?==?0)????????????//寫錯誤??
- ????????????????break;??
- ????????}??
- ????}??
- ??????
- ????fclose(from_fp);??
- ????fclose(to_fp);??
- ??
- ????return?0;??
- }??
注 意到我的fread和fwrite中的第二個參數size都是1,這樣的話我返回值就是實際讀取到的或寫入的字節數。剛開始我寫的程序不是這樣的,我是
- while(bytes_read?=?fread(buffer,?BUFFER_SIZE,?1,from_fp))??
- while(bytes_write?=?fwrite(ptr,?bytes_read,?1,?to_fp))??
這里第三個參數為1,換句話說,也就是說要讀取1個元素(返回值為1),此元素中包含BUFFER_SIZE個字節,因為我的文件不滿足這個條件,這樣的元素值不存在。于是返回的值為0,這也是為什么我的文件數據沒有復制到另一個文件的原因了,因為根本就沒有執行這個循環中的代碼。
另外一個需要注意到的問題是fread函數不能區分文件是否結尾和出錯兩種情況。所以必須使用ferror()和feof()函數來確定到底是哪種情況,所以關于文件復制還有下面另一種寫法。代碼如下:
- #include?<stdio.h>??
- #include?<string.h>??
- ??
- #define?BUFFER_SIZE??1024??
- ??
- int?main(int?argc,?char?*argv[])??
- {??
- ????FILE?*from_fp,?*to_fp;??
- ????//int?bytes_read,?bytes_write;??
- ????long?file_len?=?0;??
- ????char?buffer[BUFFER_SIZE];??
- ??
- ????if(argc?!=?3)???????//參數包括源文件名與目標文件名??
- ????{??
- ????????printf("Input?failed!\n");??
- ????????return?1;??
- ????}??
- ??
- ????if(?(from_fp?=?fopen(argv[1],"r"))?==?NULL?)????//以只讀方式打開源文件名??
- ????{??
- ????????printf("File?is?not?exist\n");??
- ????????return?1;??
- ????}??
- ??????
- ????if((to_fp?=?fopen(argv[2],"w+"))?==?NULL)??????//打開第二個文件??
- ????{??
- ????????printf("Open?file?failed!\n");????
- ????????return?1;??
- ????}??
- ??????
- ????fseek(from_fp,?0L,?SEEK_END);???????//定位文件指針到尾部??
- ????file_len?=?ftell(from_fp);??????????//獲得文件長度??
- ????fseek(from_fp,?0L,?SEEK_SET);???????//定位文件指針到開始處??
- ??
- ????while(!feof(from_fp))???????????????//判斷文件是否結束??
- ????{??
- ????????fread(buffer,?BUFFER_SIZE,?1,?from_fp);??
- ????????if(BUFFER_SIZE?>?file_len)???????????????//緩沖區長度大于文件長度??
- ????????????fwrite(buffer,?file_len,?1,?to_fp);??
- ????????else??????????????????????????????????
- ????????{??
- ????????????fwrite(buffer,?BUFFER_SIZE,?1,?to_fp);??
- ????????????file_len?-=?BUFFER_SIZE;??
- ????????}??
- ????????bzero(buffer,BUFFER_SIZE);??????//清零緩沖區??
- ????}??
- ??
- ????fclose(from_fp);??
- ????fclose(to_fp);??
- ??
- ????return?0;??
- }??
這里面多了幾個函數,其中feof就是用來檢測文件是否結尾的函數。其返回值非0時表示文件結束。還有一個函數bzero是清零一段緩沖區的函數,使用需包含頭文件string.h。注意fread和fwrite函數的書寫就是采用第三個參數為1的方式來書寫的了。