以C中读文件时,要非常小心,用二进制处理和用文本方式处理,对于用文本方式写入的文件,操作结果是相同的,但是对于用二进制写入的文件,结果却是大为不同.例如用其对.exe文件进行读取,
#include <iostream>
#include <ctime>
#include <fstream>
using namespace std;
int main(){
FILE* fp;
fp = fopen("d.txt", "wb");
char* str = "biao";
fwrite(str, strlen(str), 1, fp);
fclose(fp);
fp = fopen("test.exe", "rb");
fseek(fp, 0L, SEEK_END);
int length = ftell(fp);
cout << "File length: " << length << endl;
rewind(fp);
char ch;
int count = 0;
while (!feof(fp)) {
ch = fgetc(fp);
//cout << ch;
count++;
}
cout << endl << count << endl;
cout << (int)ch << endl;
cout << ftell(fp) << endl;
fclose(fp);
return 0;
}
文件长度是476268,当用rb时,while (!feof(fp))能正常的读到文件末,但是如果用r来读取,到最后,ftell(fp),正好是文件的长度,但用r时,while (!feof(fp))并不能到达文件尾,最后ftell(fp)的值是7859,相差太多,对图片文件也是一样的.也许对于用r和rb打开的文件操作时,对于feof(fp)来判断是否到达文件尾时的方式不一样. 即用r打开时,feof(fp)的判断是当读取遇到EOF即-1时,判断为文件结束,注意,即使是用rb方式打开文件,如果判断的时候不用while(!feof(fp))而用((ch = fgetc(fp)) != EOF),一样的是读取遇到EOF时循环就不会继续进行,即EOF只适合于文本试,但feof(fp)却会根据是用文本方式还是用二进制方式来判断自动使用不同的判断是否到达文件尾.
所以更通用一些的判断文件结束方式用feof.
通过对fread(buf, size, num, fp)的测试,当size * num相同时,如fread(buf, 255, 1, fp)与fread(buf, 1, 255, fp)的速度相差非常小,读取210M的二进制文件用了9秒多一些(缓冲区设置成256B, 128, 256, 1024时的速度都差不多,但是200K时却是13秒,看来并非是缓冲区越大越好,但是缓冲区大时,可以减少对硬盘进行操作的次数).
如用rb(二进制方式)把结构体的数据写入文件时,不会产生额外的数据,用fseek(fp, 0L, SEEK_END), ftell(fp),取得的长度正好是结构的长度*个数,但是用r(文本方式)把结构体的数据写入文件时,却会产生一些客外的数据,此时,如果想从文件中从后向前读取结构体的数据,就不能正常得到所有数据,好在从前向后读没有问题.以防万一,应该用二进制方式来操作,这样,即可以从前向后读,也可以从后向前读.在fseek中,可以用负数来相对于当前文件指针,把文件指针向前移动,fseek(fp, -sizeof(STRUCT), SEEK_CUR).