从文件中读取7M数据失败

时间:2014-07-16 11:41:02

标签: c file-io

我正在尝试从文件中读取7M数据,但它失败了。当我用Google搜索时,我发现读取数据没有限制。

下面给出的代码失败,出现分段错误。

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);

需要一些帮助

3 个答案:

答案 0 :(得分:0)

如果要将大文件的内容读入内存,您可以: 1.实际阅读它 2. mmap it。

我将介绍如何实际阅读它,并假设使用二进制模式而没有文本模式混乱。

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 );

答案 1 :(得分:0)

这里有一些可能出错的事情。

首先,没有这一行,内存分配可能会失败。 (malloc可以返回一个NULL指针,你应该检查一下。(你还应该检查文件是否打开而没有错误。)

char *buf = malloc(7008991);

接下来,在循环中。请记住,fgets读取一个,无论多长时间,最多1024-1个字节(并附加一个空字符)。请注意,对于二进制输入,使用fread可能更合适。

while(fgets(buf+i, 1024, fp)) {

之后,这是一个很好的路线,因为你真的不知道一条线是多长时间。

i+=strlen(buf); 

然而,这一行可能是你失败的原因。

if(i==7008991)break;

您要求大小完全长度为77008991字节才能中断。除非您非常确定文件的格式,否则这种可能性很小。这一行应该是if ( i >= 7008991 ) break;

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

答案 2 :(得分:0)

文件的大小很可能是7008991个字节。但是当您使用fgets读取文件时,您要求写入最多1024个字节。当您到达文件末尾时,情况并非如此。假设你已经读过7008990个字节,那么你应该用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);