fread读不出来数据 fread()函数的参数
各位老铁们好,相信很多人对fread读不出来数据都不是特别的了解,因此呢,今天就来为大家分享下关于fread读不出来数据以及 fread()函数的参数的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
fread大概只能读10k
错误原因:
你用文本方式打开了二进制文件
文本方式读取二进制数据,可能在文件结束之前将某段数据判定为文件末尾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的位置计算长度),就可以知道是否到文件尾,不需要定义结束标志;所以用二进制方式打开任何文件都是合理的
C语言中fread的一些疑问
L_o_o_n_i_e回答得不怎么准确!
我帮你解释下:
首先介绍fread函数
功能:从一个流中读数据
函数原型: int fread(void*ptr, int size, int nitems, FILE*stream);参数:用于接收数据的地址(指针)(ptr)
单个元素的大小(size):单位是字节而不是位,例如读取一个整数值就是4元素个数(nitems)
提供数据的文件指针(stream)
返回值:成功读取的元素个数
由上面介绍知道fread函数的第一个参数是个指针变量,可以指向任意类型实参!
严归正传,对于你这里的问题,你代码中的s是个结构体数组变量,跟普通数组变量一样,数组名本身就是个指针常量,所以在buffer位置写成s是没有问题的。
那么为什么你这里读会变乱码呢?
虽然你帖的代码并没有全,但从你说的读取是乱码,我大概猜到在你用fwrite函数把数据写进文件的时候是以每次一个结构体大小(也就是仅仅是数组s的一个元素而已,也就对应一个下标而已)和一个数据块的方式写进文件里的。所以当你用fread函数读取的时候,假设你在buffer位置写成s,本身语法是没有问题的,但是就相当于你把数组s的仅一个元素的数据大小当成所有s的数据存到s中,也就是没有对应起来,所以显示会是乱码。
所以你可以有两种方式实现:
方式一:
在写的时候按一次以s的一个元素的数据大小作为一个数据块依次写进文件,然后读取时候也以同样方式读出来。
代码可以这么写:
假设s的大小为:SIZE_S
for(count= 0; count< SIZE_S; count++)
fwrite(&s[count], sizeof(struct student), 1, fp);
然后读取时:
for(count= 0; count< SIZE_S; count++)
fread(&s[count], sizeof(struct student), 1, fp);
方式二:
以整个数组s的数据大小作为一个数据块一次写进文件,然后读取时也同样全部读出来,最后可以以循环的方式打印出来。
代码实现如下:
假设s的大小为:SIZE_S
fwrite(s, SIZE_S* sizeof(struct student), 1, fp);
然后读取时:
fread(s, SIZE_S* sizeof(struct student), 1, fp);
最后打印:
for(count= 0; count< SIZE_S; count++)
fread(&s[count], sizeof(struct student), 1, fp);
明白了记得给哥哥顶下~~~ ^_^
c语言中fread函数怎么用
c语言中fread函数语法为size_tfread(void*restrictbuffer,size_tsize,size_tcount,FILE*restrictstream)。buffer是指向要读取的数组中首个对象的指针,size是每个对象的大小(单位是字节),count是要读取的对象个数,stream是输入流。通过fread函数可进行数据读取,返回成功读取的对象个数。
扩展资料:
fread函数从给定输入流stream读取最多count个对象到数组buffer中(相当于以对每个对象调用size次fgetc),把buffer当作unsignedchar数组并顺序保存结果。流的文件位置指示器前进读取的字节数。
若出现错误,则流的文件位置指示器的位置不确定。若没有完整地读入最后一个元素,则其值不确定,可能小于count。若size或count为零,则fread返回零且不进行其他动作。fread不区分文件尾和错误,因此调用者必须用feof和ferror才能判断发生了什么。
如果你还想了解更多这方面的信息,记得收藏关注本站。