c库文件读取操作不正常
来源:互联网 发布:拉伸运动软件 编辑:程序博客网 时间:2024/05/16 14:00
今天在把bmp文件转为数组时, 用c库函数fread, fgetc..读出的长度总是不对, 看日志发现, 在读到80000多字节时文件指针并没按预期的长度移动, 向后跳了很多, 一时无奈, 后尝试用CFILE类库, 没问题,
在网上查了下
错误原因: 你用文本方式打开了二进制文件 文本方式读取二进制数据, 可能在文件结束之前将某段数据判定为文件末尾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库文件读取操作不正常
- C#: 文件读取操作
- C文件操作;数据文件读取
- linux c 文件读取操作一
- c++builder读取标准ini文件操作
- c语言实现读取ini文件操作
- C文件操作示例:逐行读取文本文件
- C语言的文件读取操作总结
- c++builder读取标准ini文件操作
- 常见的C文件操作,读取,写入,获取文件指针
- C语言文件读写操作,从文件读取数据
- C库 文件操作
- 读取和操作xml文件System.Xml (c#)
- C语言的文件读取与写入操作
- C语言中打开文件读取,写入的操作
- C语言/C++文件的读取与写入操作
- 第七讲:c/c++文件的读取、操作和定位
- txt文件操作 读取
- SQL Server 5120 5123错误 解决办法
- 几种strstr的比较
- HDU 2795 Billboard
- 用QPainter绘图(Painting with QPainter
- IOS 根据 指定的 字体类型 ,size ,计算 绘制 文本 所需要的 宽度与高度
- c库文件读取操作不正常
- POJ1681高消+搜索
- 表单属性
- 分布式数据库
- PHP的isset和empty的区别(3600gz.cn)
- Android Training - 网络操作(3) - 解析XML数据
- 关于SIGPIPE导致的程序退出
- 一些面向对象的设计法则 学习笔记
- struct 关键字