錯誤原因:
你用文本方式打開了二進(jìn)制文件
文本方式讀取二進(jìn)制數(shù)據(jù), 可能在文件結(jié)束之前將某段數(shù)據(jù)判定為文件末尾EOF, 所以結(jié)束讀取( 舉個例子, 比如遇到 0x00 0x00 0xff 0xff, 則文本方式方式的文件流, 認(rèn)為已經(jīng)到文件末尾, 不能讀取)
你這個38016的文件, 大概在10k左右有段數(shù)據(jù)和文件結(jié)束標(biāo)志格式相同, 文本方式讀取到10k左右就認(rèn)為文件結(jié)束了( 真正的文本文件, 結(jié)束標(biāo)志可能在磁盤簇的剩余空間中 )
所以第一種方式:
固定讀取38016次, 每次往新文件中寫一個字節(jié); 前10k次能讀取到內(nèi)容, fread返回值是1, 這樣寫過去的一字節(jié)就是讀取的字節(jié); 后28k因?yàn)樽x取失敗, fread返回值為0, 這樣temp的內(nèi)容就不會被改寫, 仍然是最后一次成功讀取的值, 但因?yàn)槭菍懘螖?shù)固定, 所以后28k就重復(fù)寫過去;
后一種方式:
根據(jù)fread的返回值來判定文件結(jié)束, 這是正確的方法; 所以讀取到10k后, 返回值為0, 表示無效, 文件結(jié)束, 所以只復(fù)制了10k內(nèi)容
CFile只支持二進(jìn)讀寫, 所以你的結(jié)果是正確的( CFile用CFile::typeText格式會報(bào)錯; CStdioFile才能文本讀寫)
用fopen返回的FILE, 如果讀取的時候沒有加b( 比如"r"), 則默認(rèn)的是文本格式; 所以請用"rb"來讀取二進(jìn)制文件, 用"wb"寫二進(jìn)制文件; 當(dāng)然如果只是復(fù)制文件的話, 純二進(jìn)制讀寫沒有問題
下面是樓主要的效果, 是一個字節(jié)讀寫的
#include <stdio.h>
int main()
{
FILE *pFileS = fopen( "s.rar", "rb" );
if( ! pFileS )
return 1;
FILE *pFileD = fopen( "d.rar", "wb+" );
unsigned char bTemp;
while( fread( &bTemp, sizeof(unsigned char), 1, pFileS) )
fwrite( &bTemp, sizeof(unsigned char), 1, pFileD );
fclose( pFileS ), fclose( pFileD );
return 0;
}
其實(shí)一個字節(jié)讀寫的話, 用fgetc和fputc就可以了, 當(dāng)然還是得以二進(jìn)制方式打開
另外單字節(jié)讀寫速度太慢; 系統(tǒng)中復(fù)制文件都是整塊讀寫的, 設(shè)置緩沖大小
比如
#include <stdio.h>
int main()
{
FILE *pFileS = fopen( "s.rar", "rb" );
if( ! pFileS )
return 1;
FILE *pFileD = fopen( "d.rar", "wb" );
unsigned char buffer[ 4 * 1024 ];
int nRead;
while( nRead = fread( buffer, sizeof(unsigned char), sizeof(buffer), pFileS ) )
fwrite( buffer, sizeof(unsigned char), nRead, pFileD );
fclose( pFileS ), fclose( pFileD );
return 0;
}
另外, fread單次讀取的總字節(jié)數(shù)有限制, 也就是說緩沖有上限; 只能通過提高次數(shù)來讀取大文件; 在這方面, 用API如ReadFile或者調(diào)用了這些API的封裝類就好得多; 當(dāng)然, 次數(shù)多對電腦來說不是問題呵呵
附:
至于文本方式不能完全讀取, 而二進(jìn)制方式能的原因-
文本方式讀取文件, 最主要的用處是一次讀取一整句( 以換行符'\n', 即二進(jìn)制的換行標(biāo)志"\r\n"結(jié)束 ), 方便用于特殊用處ReadString、fscanf(...,"%s",...)之類, 每次讀取的內(nèi)容長度是不定的; 而二進(jìn)制讀取方式Read、fread等, 都是讀取固定長度
所以文本方式讀取對EOF的判定, 是一個文件尾結(jié)束標(biāo)志, 如果是文本文件, 則這個文件尾肯定不會出現(xiàn)在文件內(nèi)容中( 因?yàn)槭遣豢纱蛴∽址麡?gòu)成的結(jié)束標(biāo)志, 人可讀的文本文件不會包括它 ), 這樣以結(jié)束標(biāo)志為文件尾則是可以的; 二進(jìn)制文件內(nèi)容可以是任意字節(jié), 如果把它當(dāng)文本文件來讀, 以文件尾為結(jié)束, 當(dāng)然可能出現(xiàn)把文件內(nèi)容判定為文件尾的情況;
二進(jìn)制讀取方式由于每次讀取固定字節(jié), 所以只需要用總文件長度( 這個數(shù)值是系統(tǒng)管理的數(shù)值, 不是計(jì)算得出來的 )減去每次讀取的長度( 或根據(jù)Seek的位置計(jì)算長度 ), 就可以知道是否到文件尾, 不需要定義結(jié)束標(biāo)志; 所以用二進(jìn)制方式打開任何文件都是合理的