在C语言中逐行逐块读取文件

在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

我需要从一个文件中读取4000行,对它们进行一些操作,然后读取下4000行,对它们进行一些操作,然后读取下4000行,依此类推,直到某个大文件的结尾。如何正确地做到这一点

这是我的基本代码,它只是读取文件中的所有行,而不是逐块读取:

#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];