我正在尝试从文件中读取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);
需要一些帮助
答案 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);