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讀取緩沖區和寫入緩沖區。
