fread大概只能读10k

从一个文件中把数据复制到另外一个文件中,我的代码如下:
while (i<38016)//文件大小为38016字节,i(unsigned int),temp(char)
{
fread(&temp,1,1,fyuv);
fwrite(&temp,1,1,fyuv1);
i++;
}
结果文件有38k,其中前面大概10k是正确的(与源文件进行二进制代码比对),后面的约28k就重复前面10k的最后一个字节,也就是后面28k所有字节完全一样。
若把代码换成:
do
{
i=fread(&temp,1,1,fyuv);
fwrite(&temp,i,1,fyuv1);
}while(i>0);
则得到的结果文件大概只有10k,且这10k与源文件的前10k一样(比对二进制代码),但是后28k就没有了。
请问我该怎么做才是正确的呢?
ps:如果用CFile类则可以正确地复制文件,但是我现在想用fread函数来实现。

错误原因:
你用文本方式打开了二进制文件

文本方式读取二进制数据, 可能在文件结束之前将某段数据判定为文件末尾EOF, 所以结束读取( 举个例子, 比如遇到 0x00 0x00 0xff 0xff, 则文本方式方式的文件流, 认为已经到文件末尾, 不能读取)

你这个38016的文件, 大概在10k左右有段数据和文件结束标志格式相同, 文本方式读取到10k左右就认为文件结束了( 真正的文本文件, 结束标志可能在磁盘簇的剩余空间中 )

所以第一种方式:
固定读取38016次, 每次往新文件中写一个字节; 前10k次能读取到内容, fread返回值是1, 这样写过去的一字节就是读取的字节; 后28k因为读取失败, fread返回值为0, 这样temp的内容就不会被改写, 仍然是最后一次成功读取的值, 但因为是写次数固定, 所以后28k就重复写过去;
后一种方式:
根据fread的返回值来判定文件结束, 这是正确的方法; 所以读取到10k后, 返回值为0, 表示无效, 文件结束, 所以只复制了10k内容

CFile只支持二进读写, 所以你的结果是正确的( CFile用CFile::typeText格式会报错; CStdioFile才能文本读写)
用fopen返回的FILE, 如果读取的时候没有加b( 比如"r"), 则默认的是文本格式; 所以请用"rb"来读取二进制文件, 用"wb"写二进制文件; 当然如果只是复制文件的话, 纯二进制读写没有问题

下面是楼主要的效果, 是一个字节读写的
#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;
}
其实一个字节读写的话, 用fgetc和fputc就可以了, 当然还是得以二进制方式打开

另外单字节读写速度太慢; 系统中复制文件都是整块读写的, 设置缓冲大小
比如
#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单次读取的总字节数有限制, 也就是说缓冲有上限; 只能通过提高次数来读取大文件; 在这方面, 用API如ReadFile或者调用了这些API的封装类就好得多; 当然, 次数多对电脑来说不是问题呵呵

附:
至于文本方式不能完全读取, 而二进制方式能的原因-
文本方式读取文件, 最主要的用处是一次读取一整句( 以换行符'\n', 即二进制的换行标志"\r\n"结束 ), 方便用于特殊用处ReadString、fscanf(...,"%s",...)之类, 每次读取的内容长度是不定的; 而二进制读取方式Read、fread等, 都是读取固定长度
所以文本方式读取对EOF的判定, 是一个文件尾结束标志, 如果是文本文件, 则这个文件尾肯定不会出现在文件内容中( 因为是不可打印字符构成的结束标志, 人可读的文本文件不会包括它 ), 这样以结束标志为文件尾则是可以的; 二进制文件内容可以是任意字节, 如果把它当文本文件来读, 以文件尾为结束, 当然可能出现把文件内容判定为文件尾的情况;
二进制读取方式由于每次读取固定字节, 所以只需要用总文件长度( 这个数值是系统管理的数值, 不是计算得出来的 )减去每次读取的长度( 或根据Seek的位置计算长度 ), 就可以知道是否到文件尾, 不需要定义结束标志; 所以用二进制方式打开任何文件都是合理的
温馨提示:内容为网友见解,仅供参考
第1个回答  2009-01-05
fread函数调用失败的时候,你的两个程序段的现象就是自然而然的,至于为什么fread会失败,可能还是你的操作系统不够稳定,或者兼容性不好,修改fread的参数应该可以改善
unsigned int i=0;
char temp[1024];
while (i<38016)//文件大小为38016字节
{
int len = fread(&temp,1,1024,fyuv);
if(len>0)
{
fwrite(&temp,1,len,fyuv1);
i+=len;
}
}
第2个回答  2009-01-05
我想知道temp是怎么定义的,怎么会变成&temp,好像合理的方法是temp应该是一个指针,temp是指向内存块的指针。

另外,楼主有个很严重的错误:每次只读一个字节,这样的效率非常低,应该是每次读取一大块数据,然后判断函数的返回值,根据返回值判定是否文件已经读完。对于写文件也类似。
第3个回答  2009-01-05
没道理吧!

所有的代码都给出来看看,我不信会这样!
第4个回答  2009-01-05
一个一个来吧。get和put

fread大概只能读10k
你这个38016的文件, 大概在10k左右有段数据和文件结束标志格式相同, 文本方式读取到10k左右就认为文件结束了( 真正的文本文件, 结束标志可能在磁盘簇的剩余空间中 )所以第一种方式:固定读取38016次, 每次往新文件中写一个字节; 前10k次能读取到内容, fread返回值是1, 这样写过去的一字节就是读取的...

C语言 fread能从文件中读10bit数据存入int型中吗?
内存、文件操作都只能以字节为单位,字节是最小的单位,也就是 8bit ,所以做法是先读 16bit 。再 & 0x03FF

文件复制,请用C语言。用fread函数最好。
a+是文本文件的读取方式,改成ab会好很多(2进制读取),fread一次最多只能读进64K的东西,fread的第2个参数要小于64K。你的40W肯定不行,建议你先把读取弄好,然后再去想存储

C语言中fread函数,当文件流缓冲中剩余长度小于需要读取的长度时的问题...
fread在fp_in缓冲区中剩余字节为0的时候才会产生一个异常让内核去处理,内核收到这个异常,就会读取文件,将fp_in的缓冲区重新填满。也就是说:如果只剩下15个了,你要读20个,那么就会先读15个到g_buffer里,然后产生一个异常,内核重新填满缓冲区,然后再从缓冲区里读5个字节。

C语言 用fread 读取文件的时候,只能读第一行,后面的都读不出来怎么回事...
是你多输出了'\\n'的缘故吧。解决办法:1-不写'\\n'2-读取'\\n

fread函数问题
文件指针是自动移动的,你只能读第一个,肯定是程序代码有问题,把代码贴出来看看。

...写入的文件字节数很多,为什么读的时候只能读到固定字节的数,而且...
size (例如 2048字节)while (fgets(buff,buff_size,fin) !=NULL){ };fgets 是读一行,行长度不大于 buff_size , buff 里就放 完整的一行,大于,就读入\/放入 buff_size 个字节。fread, 也要提供 大小。buff_size 数值大小 也可以很大,只要动态分配能成功分配就行,并不限于 1k,2k.

c语言中fread函数怎么用
c语言中fread函数语法为size_t fread( void *restrict buffer, size_t size, size_t count, FILE *restrict stream )。buffer是指向要读取的数组中首个对象的指针,size是每个对象的大小(单位是字节),count是要读取的对象个数,stream是输入流。通过fread函数可进行数据读取,返回成功读取的对象个数...

C语言~我写一个TXT格式的文件在D盘 然后用这个语句读入 可是显示出来...
fread函数、fwrite函数只能读写二进制格式的文件。因为你的文件是文本格式的(除非你是用fwrite函数写入的数据),所以不能用fread函数正确地读出来。

php 怎么用zend加密
ZendGuard是一款php的加密工具,它可以编译php源码变为字节码 加密的具体步骤如下:1:在网上下载ZendGuard 关于PHP文件加密的软件 2:安装完毕以后,找到bin目录下zendenc.exe 。注:(别忘记搞上破解版。)3:使用方法,先找一个你要加密的php文件,比如iii.php。4:然后在命令行里面输入: zendenc ...

相似回答