小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

關(guān)于fread的問(wèn)答

 haodafeng_org 2011-01-28
從一個(gè)文件中把數(shù)據(jù)復(fù)制到另外一個(gè)文件中,我的代碼如下:
while (i<38016)//文件大小為38016字節(jié),i(unsigned int),temp(char)
{
 fread(&temp,1,1,fyuv);
 fwrite(&temp,1,1,fyuv1);
 i++;
}
結(jié)果文件有38k,其中前面大概10k是正確的(與源文件進(jìn)行二進(jìn)制代碼比對(duì)),后面的約28k就重復(fù)前面10k的最后一個(gè)字節(jié),也就是后面28k所有字節(jié)完全一樣。
若把代碼換成:
do
{
 i=fread(&temp,1,1,fyuv);
 fwrite(&temp,i,1,fyuv1);
}while(i>0);
則得到的結(jié)果文件大概只有10k,且這10k與源文件的前10k一樣(比對(duì)二進(jìn)制代碼),但是后28k就沒(méi)有了。
請(qǐng)問(wèn)我該怎么做才是正確的呢?
錯(cuò)誤原因:
你用文本方式打開(kāi)了二進(jìn)制文件

文本方式讀取二進(jìn)制數(shù)據(jù), 可能在文件結(jié)束之前將某段數(shù)據(jù)判定為文件末尾EOF, 所以結(jié)束讀取( 舉個(gè)例子, 比如遇到 0x00 0x00 0xff 0xff, 則文本方式方式的文件流, 認(rèn)為已經(jīng)到文件末尾, 不能讀取)

你這個(gè)38016的文件, 大概在10k左右有段數(shù)據(jù)和文件結(jié)束標(biāo)志格式相同, 文本方式讀取到10k左右就認(rèn)為文件結(jié)束了( 真正的文本文件, 結(jié)束標(biāo)志可能在磁盤(pán)簇的剩余空間中 )

所以第一種方式:
固 定讀取38016次, 每次往新文件中寫(xiě)一個(gè)字節(jié); 前10k次能讀取到內(nèi)容, fread返回值是1, 這樣寫(xiě)過(guò)去的一字節(jié)就是讀取的字節(jié); 后28k因?yàn)樽x取失敗, fread返回值為0, 這樣temp的內(nèi)容就不會(huì)被改寫(xiě), 仍然是最后一次成功讀取的值, 但因?yàn)槭菍?xiě)次數(shù)固定, 所以后28k就重復(fù)寫(xiě)過(guò)去;
后一種方式:
根據(jù)fread的返回值來(lái)判定文件結(jié)束, 這是正確的方法; 所以讀取到10k后, 返回值為0, 表示無(wú)效, 文件結(jié)束, 所以只復(fù)制了10k內(nèi)容

CFile只支持二進(jìn)讀寫(xiě), 所以你的結(jié)果是正確的( CFile用CFile::typeText格式會(huì)報(bào)錯(cuò); CStdioFile才能文本讀寫(xiě))
用fopen返回的FILE, 如果讀取的時(shí)候沒(méi)有加b( 比如"r"), 則默認(rèn)的是文本格式; 所以請(qǐng)用"rb"來(lái)讀取二進(jìn)制文件, 用"wb"寫(xiě)二進(jìn)制文件; 當(dāng)然如果只是復(fù)制文件的話, 純二進(jìn)制讀寫(xiě)沒(méi)有問(wèn)題

下面是樓主要的效果, 是一個(gè)字節(jié)讀寫(xiě)的
#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í)一個(gè)字節(jié)讀寫(xiě)的話, 用fgetc和fputc就可以了, 當(dāng)然還是得以二進(jìn)制方式打開(kāi)

另外單字節(jié)讀寫(xiě)速度太慢; 系統(tǒng)中復(fù)制文件都是整塊讀寫(xiě)的, 設(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ù)有限制, 也就是說(shuō)緩沖有上限; 只能通過(guò)提高次數(shù)來(lái)讀取大文件; 在這方面, 用API如ReadFile或者調(diào)用了這些API的封裝類(lèi)就好得多; 當(dāng)然, 次數(shù)多對(duì)電腦來(lái)說(shuō)不是問(wèn)題呵呵

附:
至于文本方式不能完全讀取, 而二進(jìn)制方式能的原因-
文 本方式讀取文件, 最主要的用處是一次讀取一整句( 以換行符'\n', 即二進(jìn)制的換行標(biāo)志"\r\n"結(jié)束 ), 方便用于特殊用處ReadString、fscanf(...,"%s",...)之類(lèi), 每次讀取的內(nèi)容長(zhǎng)度是不定的; 而二進(jìn)制讀取方式Read、fread等, 都是讀取固定長(zhǎng)度
所以文本方式讀取對(duì)EOF的判定, 是一個(gè)文件尾結(jié)束標(biāo)志, 如果是文本文件, 則這個(gè)文件尾肯定不會(huì)出現(xiàn)在文件內(nèi)容中( 因?yàn)槭遣豢纱蛴∽址麡?gòu)成的結(jié)束標(biāo)志, 人可讀的文本文件不會(huì)包括它 ), 這樣以結(jié)束標(biāo)志為文件尾則是可以的; 二進(jìn)制文件內(nèi)容可以是任意字節(jié), 如果把它當(dāng)文本文件來(lái)讀, 以文件尾為結(jié)束, 當(dāng)然可能出現(xiàn)把文件內(nèi)容判定為文件尾的情況;
二進(jìn)制讀取方式 由于每次讀取固定字節(jié), 所以只需要用總文件長(zhǎng)度( 這個(gè)數(shù)值是系統(tǒng)管理的數(shù)值, 不是計(jì)算得出來(lái)的 )減去每次讀取的長(zhǎng)度( 或根據(jù)Seek的位置計(jì)算長(zhǎng)度 ), 就可以知道是否到文件尾, 不需要定義結(jié)束標(biāo)志; 所以用二進(jìn)制方式打開(kāi)任何文件都是合理的 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多