C/C++中读取文件判断是否读取结束

最近用C++读取文件时遇到了一个问题,读取如下图所示的文件时,使用C中的feof()判断是否读取结束,总会在文件末尾处总会多读一遍。

C/C++中读取文件判断是否读取结束_第1张图片

可以看到我读取的文件格式是比较简单的,没两行为一对,第一行有两个int类型的数字,第二行是一个字符串,包含图像的名称。

先上我读取文件的代码:

 

void read(string name)
{
	FILE *file = fopen(name.c_str(), "r");
	while (!feof(file))
	{
		int i, j;
		fscanf(file, "%d%d\n", &i, &j);

		char filename[100];
		fgets(filename, 100, file);
		filename[strlen(filename) - 1] = '\0';
	}
}

可以看到,读取的代码非常简单,但是这样会出现一个问题,最后一行会重复输出一遍。

 

造成这个问题的原因在于feof在真正文件读取结束后还会继续在判断一遍才会结束。

为了解决这个问题,有人是使用了如下方法

 

char c;
c = fgetc(fp);
while(!feof(fp))
{
	printf("%X/n", c); 
	c = fgetc(fp);
} 	printf("%X/n", c); 
	c = fgetc(fp);
} 

这种方法确实可以避免重复读取最后一行的问题,但是这种方法更加适合于每次读取单个字符的情况,对于我遇到的这种,需要读取int和字符串的情况就不是很适用,最终我在网上找到了一种万无一失的方法解决feof的问题,那就是不用它。。。

 

我们适用fseek和ftell来配合判断是否读取到文件末尾。

 

void read(string name)
{
	FILE *file = fopen(name.c_str(), "r");

	fseek(file, 0L, SEEK_END);
	long end = ftell(file);
	fseek(file, 0L, SEEK_SET);
	long start = ftell(file);

	while (end != start)
	{
		int i, j;
		fscanf(file, "%d%d\n", &i, &j);

		char filename[100];
		fgets(filename, 100, file);
		if (filename[strlen(filename) - 1] == '\n')
			filename[strlen(filename) - 1] = '\0';

		cout << filename << endl;
		start = ftell(file);
	}
}

大体思路就是首先通过fseek得到文件末尾的位置,然后在读取文件以后不断计算当前读取的文件位置,如果读取后发现当前位置与文件末尾位置相同,则停止继续读取文件。

 

这种方法的好处是万金油,记住这一种,以后遇到所有需要读取全部文件的情况都可以适用。简单易懂。

当然利用C++的方法也可以实现这一需求,但是有些情况下C++的读写速度明显低于C语言,而且C++兼容C语言。

 

 

你可能感兴趣的:(C++)