fgets 一次读取一行数据

上一篇文章我们介绍过一次性读取一个字符,这样读取更加精确,但有不同的需求,比如需要一次读取一行或一段。本文将介绍如何一次读取一行内容,提供了两个函数,并分析了两个函数的区别。

示例文件:

Open file
Opens the file whose name is specified in the parameter filename and associates it with a stream that can be identified in future operations by the FILE pointer returned.

The operations that are allowed on the stream and how these are performed are defined by the mode parameter.

The returned stream is fully buffered by default if it is known to not refer to an interactive device (see setbuf).

The returned pointer can be disassociated from the file by calling fclose or freopen. All opened files are automatically closed on normal program termination.

The running environment supports at least FOPEN_MAX files open simultaneously.

方法一,也是使用最多的方法:

int readFile(char* pfile)
{
	FILE* pFile = fopen(pfile, "r");
	if (NULL == pFile) return -1;

	char buf[1024];
	while (fgets(buf, 1024, pFile))
	{
		printf("%s", buf);
	}

	fclose(pFile);
	return 0;
}

方法一中,是设定一个buf为1024个字节,向这个buf填入内容,然后打印,当一行中的数据超过了1024个字节的时候,会分多次将整行内容读取。此时会有一个问题出现,如果你希望在每一行中查找一个单词如“from”,而“from”这个单词刚好在这一行的1022的位置,此时这个单词就会被截断。为了解决这个问题,本文提出了动态分配空间来储存整行数据到malloc的空间中,然后进行查找、对比和打印。代码如下:

int readFile(char* pfile)
{
	FILE* pFile = fopen(pfile, "r");
	if (NULL == pFile) return -1;

	char line[1024];
	char* p_malloc = NULL;
	while (fgets(line, sizeof(line), pFile) != NULL)
	{
		// 判断是否包含\n
		if (NULL == strstr(line, "\n"))
		{
			// 如果不包含,则判断p_malloc是否已经分配了空间
			if (p_malloc == NULL)
			{
				// 如果没有分配空间,那证明是一个全新行,读取第一段数据
				p_malloc = (char*)malloc(sizeof(line));
				// 将内容拷贝进新申请的空间中
				strcpy(p_malloc, line);
			}
			else
			{
				// 如果 p_malloc != NULL 证明不是新行,而是在某一行读取的第2+n次
				// 拓展的空间由以前空间的大小加上新读取到的数据的大小
				p_malloc = (char*)realloc(p_malloc,
					(strlen(p_malloc) + 1) + sizeof(line));
				// 将内容追加到拓展后的空间中
				strcat(p_malloc, line);
			}
		}
		else
		{
			// 包含\n的情况下,判断p_malloc是否已经分配过空间
			if (p_malloc == NULL)
			{
				// 如果没有分配过空间,证明是个新行,而且buf足够容纳读取出来的内容
				// 打印内容(buf可以容纳)
				printf("%s", line);
			}
			else
			{
				// 如果分配过空间,证明不是新行,而且是第二次读取
				// 拓展空间,将后面读取进来的字符串存入
				p_malloc = (char*)realloc(p_malloc, 
					(strlen(p_malloc) + 1) + sizeof(line));
				strcat(p_malloc, line);

				// 打印内容(大于buf空间)
				printf("%s", p_malloc);

				// 释放申请的空间
				free(p_malloc);
				p_malloc = NULL;
			}
		}

	}

	fclose(pFile);
	return 0;
}

 

发表评论