使用读取功能使用C(大于4GB)读取大文件,导致问题

sri*_*eet 7 c unix file-io posix

我必须编写用于读取大文件的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);
}
Run Code Online (Sandbox Code Playgroud)

我在这里遇到的问题是,只要传递的参数(size参数)小于264000000字节,它似乎能够读取.我每个周期都会获得越来越大的块变量.

当我传递264000000字节或更多时,读取失败,即:根据检查使用,read返回-1.

谁能指出我为什么会这样?我正在使用cc在正常模式下编译,而不是使用DD64.

小智 8

首先,你为什么需要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;

}
Run Code Online (Sandbox Code Playgroud)

我也冒昧地删除结果变量和所有相关逻辑,因为我相信它可以简化.

编辑:我注意到有些系统(最值得注意的是,BSD)没有O_LARGEFILE,因为那里不需要它.所以,我在开头添加了#ifdef,这将使代码更具可移植性.


Jay*_*Jay 2

lseek 函数可能难以支持大文件大小。尝试使用lseek64

请检查链接以查看使用 lseek64 函数时需要定义的关联宏。