5

linux下c语言编程,获取超大文件大小(size超过2GB)

 3 years ago
source link: https://blog.popkx.com/linux-c-get-large-file-size-lager-than-2gb/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

linux下c语言编程,获取超大文件大小(size超过2GB)

发表于 2018-06-11 11:06:55   |   已被 访问: 1,387 次   |   分类于:   Linux笔记   |   暂无评论

最近做一个项目,需要获取文件大小,而文件大小又是超过 2GB 的。这就导致很多 c 标准函数不能正常工作。

linux c语言获取文件大小常用方法


常用方法有两类:

  • 利用 seek 系函数。
    以 lseek 函数为例,它可以将定位要读写文件的位置,正常情况下,它会返回当前读写指针位置。让其指向文件末尾,即可获得文件大小。
  • 利用 stat 系函数。
    推荐用这个函数,比较简单,是专用来获取文件信息的函数。

seek 系函数获取文件大小

直接上代码:

int get_file_size(char* filename) 
{ 
  int fd = open(filename, O_RDWR, 0666); 
  if(fd<0) 
      return 0; 
  off_t size = lseek(fd,0,SEEK_END); 
  close(fp); 

  return size; 
} 

stat 系函数获取文件大小

off_t get_file_size(char* filename) 
{ 
  struct stat sstat; 
  stat(filename, &sstat); 
  off_t size=sstat.st_size; 

  return size; 
}

为何seek函数stat函数不能获取大于2GB的超大文件大小


以上介绍的两个例子在获取小于 2GB 的文件大小时,可以很好的工作,但是当文件大小大于 2GB 时,就不正常了。

其实,这主要是数据类型的长度限制的。lseek 的函数原型如下:

off_t lseek(int fildes,off_t offset ,int whence);

struct stat 的原型如下:

struct stat {
        mode_t     st_mode;       //文件对应的模式,文件,目录等
        ino_t      st_ino;       //inode节点号
        dev_t      st_dev;        //设备号码
        dev_t      st_rdev;       //特殊设备号码
        nlink_t    st_nlink;      //文件的连接数
        uid_t      st_uid;        //文件所有者
        gid_t      st_gid;        //文件所有者对应的组
        off_t      st_size;       //普通文件,对应的文件字节数*****
        time_t     st_atime;      //文件最后被访问的时间
        time_t     st_mtime;      //文件内容最后被修改的时间
        time_t     st_ctime;      //文件状态改变时间
        blksize_t  st_blksize;    //文件内容对应的块大小
        blkcnt_t   st_blocks;     //文件内容对应的块数量
      };

会发现,咱们要返回的值类型都是 off_t 的。
执行以下代码:

printf("sizeof(off_t): %d\n", sizeof(off_t));

输出如果是 4,就很好理解为何以上函数只能获取小于 2GB 的文件大小了。

linux C语言获取大于2GB的超大文件大小


在/usr/include中执行shell命令:

grep __USE_FILE_OFFSET64 /usr/include/* -r

查找 off_t类型的定义可以看出,off_t其实拥有两种类型:__off_t和__off64_t

要使 off_t为__off64_t类型,必须

#define __USE_FILE_OFFSET64.

还找到了这个:

#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
# define __USE_FILE_OFFSET64    1
#endif

所以,我们在包含所有头文件之前,需要:

#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif

#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif

这样就可以64位偏移地址形式操作文件。

咱们以 stat 函数为例,使用其 64 位类型的函数,代码如下:

#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif

#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>


off_t get_file_size(const char *filename)  
{  
    struct stat64 buf;  
    if(stat64(filename, &buf)<0)  
    {
        printf("cannot open file\n");
        return 0;  
    } 
    printf("st_size: %lld\n", (off_t)buf.st_size);
    return (off_t)buf.st_size;  
}

应该很容易看懂,这样,咱们就完成了 linux 下C语言获取大于2GB的超大文件大小的代码了。

阅读更多:   Linux笔记


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK