fwrite(buff, sizeof(buff), 1, pFile);//返回實際寫入的完整項數,參數3盡量填1,簡單粗暴 fread(buff, sizeof(buff), 1, pFile);//返回實際讀取的完整項數,參數3盡量填1,簡單粗暴
文件內容:
每4字節復制舊文件到新文件,忽略錯誤檢查:
FILE *pFileSource = fopen("C++ Primer.exe", "rb");//CreateFile FILE *pFileDest = fopen("C++ Primer2.exe", "wb"); char buffSource[16] = { 0 };//設置很小的緩沖區,便於測試 char buffDest[16] = { 0 }; setvbuf(pFileSource, buffSource, _IOFBF, 7);//只給7字節,便於測試 setvbuf(pFileDest, buffDest, _IOFBF, 7); fseek(pFileSource, 0, SEEK_END); long fileSize = ftell(pFileSource); rewind(pFileSource); unsigned int buff = 0; for (long i = 0; i < fileSize / 4; i++) { fread(&buff, sizeof(buff), 1, pFileSource);//ReadFile fwrite(&buff, sizeof(buff), 1, pFileDest);//直接寫入緩沖區,滿了調用flush } unsigned char byte = '\0'; for (long i = 0; i < fileSize % 4; i++) { fread(&byte, sizeof(byte), 1, pFileSource); fwrite(&byte, sizeof(byte), 1, pFileDest); } fflush(pFileDest);//WriteFile fclose(pFileSource);//CloseHandle fclose(pFileDest);
以上代碼將緩沖區大小設為7,但是實際向下舍入到 2的整數倍,即6字節。
第1次fread讀取6字節填滿緩沖區,再取出4字節給代碼中的unsigned int buff = 0;此變量在0019FF0C處。
F10單步,第1次fwrite寫入4字節到寫緩沖區,watch切換到pFileDest觀察。再觀察要寫入的文件,發現大小沒寫入任何數據,因為寫緩沖區沒滿。
F10單步,第2次fread讀取6字節
F10單步,第2次fwrite,0506寫入緩沖區末尾,這時滿了,將整個6字節緩沖區寫入文件。再調整_ptr到_base,並把0708寫入緩沖區。打開文件,發現有6字節數據。
F10單步,第3次fread,緩沖區數據足夠,未讀入新數據,有變化的是_ptr
F10單步,第3次fwrite,剛好填滿寫緩沖區,打開文件發現依舊是6字節,未寫入。
F10單步,第4次fread,讀入6字節新數據
F10單步,第4次fwrite,緩沖區已滿,調用fflush,打開文件發現多了6字節
總結:第一次fread和fwrite時會分別提供默認4096字節的讀和寫緩沖區,也可以自己調用setvbuf函數設置緩沖區。fread從文件讀取_bufsiz大小的數據存放在讀緩沖區,后續如無必要,不會讀文件,而是直接讀緩沖區。同理,fwrite將數據寫入寫緩沖區,除非緩沖區已滿,否則不寫入文件。兩者都通過移動指針_ptr讀取緩沖區和寫入緩沖區。