在C语言中逐行逐块读取文件
我需要从一个文件中读取4000行,对它们进行一些操作,然后读取下4000行,对它们进行一些操作,然后读取下4000行,依此类推,直到某个大文件的结尾。如何正确地做到这一点 这是我的基本代码,它只是读取文件中的所有行,而不是逐块读取:在C语言中逐行逐块读取文件,c,C,我需要从一个文件中读取4000行,对它们进行一些操作,然后读取下4000行,对它们进行一些操作,然后读取下4000行,依此类推,直到某个大文件的结尾。如何正确地做到这一点 这是我的基本代码,它只是读取文件中的所有行,而不是逐块读取: #include <stdio.h> #include <string.h> #define bufSize 1024 int main(int argc, char *argv[]) { FILE* fp; char b
#include <stdio.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE* fp;
char buf[bufSize];
if (argc != 2)
{
fprintf(stderr, "Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
while (fgets(buf, sizeof(buf), fp) != NULL)
{
buf[strlen(buf) - 1] = '\0'; /* eat the newline fgets() stores */
printf("%s\n", buf);
}
fclose(fp);
return 0;
}
#包括
#包括
#定义bufsize1024
int main(int argc,char*argv[])
{
文件*fp;
字符buf[bufSize];
如果(argc!=2)
{
fprintf(stderr,“用法:%s\n”,argv[0]);
返回1;
}
if((fp=fopen(argv[1],“r”)==NULL)
{/*开源文件*/
perror(“fopen源文件”);
返回1;
}
while(fgets(buf,sizeof(buf),fp)!=NULL)
{
buf[strlen(buf)-1]='\0';/*吃新行fgets()存储*/
printf(“%s\n”,buf);
}
fclose(fp);
返回0;
}
确定,然后在堆上分配一个二维数组,并声明一个类型为size\t
的变量n以跟踪行数。请尝试以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE* fp;
if (argc != 2)
{
fprintf(stderr, "Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
size_t n = 0;
char(*buf)[bufSize] = malloc(bufSize * 4000);
if (!buf) {
fprintf(stderr, "Error - Failed to allocate memory.\n");
fclose(fp);
return 1;
}
while (1)
{
if (fgets(buf[n], bufSize, fp) != NULL) {
n++;
if (n == 4000) {
/* do something */
// ...
n = 0;
}
}
else {
// do something with leftover
break;
}
}
free(buf);
fclose(fp);
return 0;
}
#包括
#包括
#包括
#定义bufsize1024
int main(int argc,char*argv[])
{
文件*fp;
如果(argc!=2)
{
fprintf(stderr,“用法:%s\n”,argv[0]);
返回1;
}
if((fp=fopen(argv[1],“r”)==NULL)
{/*开源文件*/
perror(“fopen源文件”);
返回1;
}
尺寸n=0;
字符(*buf)[bufSize]=malloc(bufSize*4000);
如果(!buf){
fprintf(stderr,“错误-分配内存失败。\n”);
fclose(fp);
返回1;
}
而(1)
{
if(fgets(buf[n],bufSize,fp)!=NULL){
n++;
如果(n==4000){
/*做点什么*/
// ...
n=0;
}
}
否则{
//用剩下的做点什么
打破
}
}
免费(buf);
fclose(fp);
返回0;
}
问题出在哪里
您需要使用2个循环。外部的一个会重复读大量的行,直到EOF
代码可能类似于以下草图:
...
while (1)
{
/* read <= 4000 lines and process */
}
而不是mallocing。这将节省执行alloc/dealoc序列的时间,或者使用calloc(400*bufSize)在顶层(循环外部)执行分配代码>
但这取决于个人偏好,因为当前设置总共使用了大约4MB的内存
关于性能:
静态分配内存可能会带来一些速度优势。
您还可以尝试增加stdio使用的缓冲区大小(通过setbuffer()
变量从文件中读取较大的块)
这是否会产生任何明显的影响取决于您应该采取的一些性能度量(如果首先出现问题)有什么错误?您可以详细说明吗?此答案不适用于源文件不是4000行偶数倍的情况。此外,答案无法将分配的内存传递给free()
退出程序之前。@SebastianRockefeller我更新了代码。请检查一下。关于这一行:buf[strlen(buf)-1]='\0';
,这不是一个万无一失的方法。有两种可能会失败。1)这一行比1023字节长2)文件的最后一行没有以新行结尾。建议:char*newline=NULL;如果(换行符=strstrstr(buf,“\n”){*newline='\n';}
而不是此行:int line=0
应该声明行
而不是行
,我建议实际的行是:size\u t lines=0代码>发布的答案非常简单good@user3629249:感谢您指出问题,并相应地编辑了答案。
size_t lines = 0; /** next index to be used with lineBuffer
(and number of lines already stored)*/
char *lineBuffer[4000];
char buf[bufSize];
while (lines < 4000 && fgets(buf, sizeof(buf), fp) != NULL)
{
buf[strlen(buf) - 1] = '\0';
lineBuffer[lines] = malloc(strlen(buf);
strcpy(lineBuffer[lines], buf);
lines++;
}
if (lines == 0)
{
break; /* we are done*/
}
/* do processing on data */
/* deallocate dynamic memory */
for (int i = lines - 1; lines>=0; i--)
{
free(lineBuffer[i]);
}
lines = 0;
char lineBuffer[4000][bufSize];