C 从文件读取数据失败

C 从文件读取数据失败,c,file-io,C,File Io,我试图从文件中读取700万个数据,但失败了。当我在谷歌上搜索时,我发现阅读数据没有限制 下面给出的代码由于分段错误而失败 char *buf = malloc(7008991); FILE *fp = fopen("35mb.txt", "rb"); long long i = 0; long long j = 0; while(fgets(buf+i, 1024, fp)) { i+=strlen(buf); if(i==7008991)break; } printf("rea

我试图从文件中读取700万个数据,但失败了。当我在谷歌上搜索时,我发现阅读数据没有限制

下面给出的代码由于分段错误而失败

char *buf = malloc(7008991);
FILE *fp = fopen("35mb.txt", "rb");
long long i = 0;
long long j = 0;
while(fgets(buf+i, 1024, fp)) {
    i+=strlen(buf);
    if(i==7008991)break;
}
printf("read done");
printf("ch=%s\n", buf);

需要帮助

如果要将大文件的内容读入内存,可以: 1.真的读了吗 2.mmap它

我将介绍如何实际读取它,并假设使用二进制模式,而不使用文本模式

FILE* fp;
// Open the file
fp = fopen ("35mb.txt", "rb");
if ( fp == NULL ) return -1; // Fail

// Get file length, there are many use to do this like fstat
// TODO: check failure
fseek ( fp, 0, SEEK_END );
flen = ftell ( fp );
fseek ( fp, 0, SEEK_SET );

if ( fread ( buffer, flen, 1, fp ) != 1 ) {
  // Fail
}

fclose ( fp );

这里有一些事情可能会出错

首先,没有这一行,内存分配可能会失败。(Malloc可以返回空指针,您应该对此进行检查。(您还应该检查文件是否正确打开。)

下一步,在循环中。请记住,fgets读取一行,而不管它有多长,最多可达1024-1字节(并附加一个空字符)。对于二进制输入,使用可能更合适

while(fgets(buf+i, 1024, fp)) {
在那之后,这是一条很好的线,因为你真的不知道一条线有多长

i+=strlen(buf); 
然而,这一行可能就是你失败的原因

if(i==7008991)break;
您要求的大小必须是正好77008991字节长才能中断。除非您非常确定文件的格式,否则这不太可能。如果(i>=7008991)中断,这一行可能应为


您可能也应该用命名常量替换显式大小。

文件的大小很可能正好是
7008991
字节。但是当您使用
fgets
读取文件时,您要求最多写入
1024
字节。当您到达文件末尾时,情况并非如此。假设您已经读取了
7008990
bytes,那么您应该使用:
fgets(buf+i,1,fp)
调用fgets,因为您的缓冲区只剩下一个字节

另一个问题是,您希望在程序结束时打印缓冲区。要使其正常工作,缓冲区必须以NUL结尾。因此,您需要比文件大小多分配一个字节。
fgets
将自动附加NUL字节

另一个问题是增加计数器的方式:
i+=strlen(buf)
这是错误的,正确的代码是:
i=strlen(buf)

所有这些都假设代码中没有NUL字节。正如注释中已经解释的,只有在处理文本文件时才使用
fgets
更明智。在读取二进制文件时,最好使用
fread

更正后的代码为:

unsigned long FILE_SIZE = 7008991+1;
char *buf = malloc(FILE_SIZE);
FILE *fp = fopen("35mb.txt", "rb");
long long i = 0;
long long j = 0;
while(fgets(buf+i, FILE_SIZE-i, fp)) {
    i = strlen(buf);
    if(i==7008991)break;
}
printf("read done");
printf("ch=%s\n", buf);

你确定你的
malloc
没有失败吗。malloc最多可以分配多少内存?你确定要使用二进制模式的fgets吗?还有i(或buf+i)错误地增加,退出条件太小,无法覆盖许多实际情况。请您纠正我在代码中的错误。您的标题是700k,问题是70k,您的malloc~7MB,输入文件名为“35mb.txt”。您确定这些数字中的任何一个吗?
unsigned long FILE_SIZE = 7008991+1;
char *buf = malloc(FILE_SIZE);
FILE *fp = fopen("35mb.txt", "rb");
long long i = 0;
long long j = 0;
while(fgets(buf+i, FILE_SIZE-i, fp)) {
    i = strlen(buf);
    if(i==7008991)break;
}
printf("read done");
printf("ch=%s\n", buf);