![](/img/trans.png)
[英]Using fread function: size to be read is greater than available for reading
[英]Reading a large file using C (greater than 4GB) using read function, causing problems
我必须编写用于读取大文件的C代码。 代码如下:
int read_from_file_open(char *filename,long size)
{
long read1=0;
int result=1;
int fd;
int check=0;
long *buffer=(long*) malloc(size * sizeof(int));
fd = open(filename, O_RDONLY|O_LARGEFILE);
if (fd == -1)
{
printf("\nFile Open Unsuccessful\n");
exit (0);;
}
long chunk=0;
lseek(fd,0,SEEK_SET);
printf("\nCurrent Position%d\n",lseek(fd,size,SEEK_SET));
while ( chunk < size )
{
printf ("the size of chunk read is %d\n",chunk);
if ( read(fd,buffer,1048576) == -1 )
{
result=0;
}
if (result == 0)
{
printf("\nRead Unsuccessful\n");
close(fd);
return(result);
}
chunk=chunk+1048576;
lseek(fd,chunk,SEEK_SET);
free(buffer);
}
printf("\nRead Successful\n");
close(fd);
return(result);
}
我在这里遇到的问题是,只要传递的参数(size参数)小于264000000字节,它似乎能够读取。 我每个周期都会获得越来越大的块变量。
当我传递264000000字节或更多时,读取失败,即:根据检查使用,read返回-1。
谁能指出我为什么会这样? 我正在使用cc在正常模式下编译,而不是使用DD64。
首先,为什么你的循环中需要lseek()
? read()
将按文件读取的字节数提前文件中的光标。
并且,对于主题:long和chunk分别具有最大值2147483647
,任何大于该值的数字实际上将变为负数。
您想使用off_t
声明chunk: off_t chunk
,并将size作为size_t
。 这是lseek()
失败的主要原因。
然后,正如其他人注意到的那样,你不想在循环中free()
你的缓冲区。
另请注意,您将覆盖已阅读的数据。 另外, read()
不一定会读出你所要求的数量,所以最好按实际读取的字节数推进块,而不是你想要读取的字节数。
考虑到所有问题,正确的代码应该看起来像这样:
// Edited: note comments after the code
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
int read_from_file_open(char *filename,size_t size)
{
int fd;
long *buffer=(long*) malloc(size * sizeof(long));
fd = open(filename, O_RDONLY|O_LARGEFILE);
if (fd == -1)
{
printf("\nFile Open Unsuccessful\n");
exit (0);;
}
off_t chunk=0;
lseek(fd,0,SEEK_SET);
printf("\nCurrent Position%d\n",lseek(fd,size,SEEK_SET));
while ( chunk < size )
{
printf ("the size of chunk read is %d\n",chunk);
size_t readnow;
readnow=read(fd,((char *)buffer)+chunk,1048576);
if (readnow < 0 )
{
printf("\nRead Unsuccessful\n");
free (buffer);
close (fd);
return 0;
}
chunk=chunk+readnow;
}
printf("\nRead Successful\n");
free(buffer);
close(fd);
return 1;
}
我也冒昧地删除结果变量和所有相关逻辑,因为我相信它可以简化。
编辑:我注意到一些系统(最值得注意的是,BSD)没有O_LARGEFILE
,因为那里不需要它。 所以,我在开头添加了#ifdef,这将使代码更具可移植性。
lseek函数可能难以支持大文件大小。 尝试使用lseek64
请检查链接以查看使用lseek64函数时需要定义的关联宏。
如果是32位机器,则读取大于4gb的文件会引起一些问题。 因此,如果您正在使用gcc编译器,请尝试使用宏-D_LARGEFILE_SOURCE=1
和-D_FILE_OFFSET_BITS=64
。
请检查此链接
如果您正在使用任何其他编译器检查类似类型的编译器选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.