如何获取一个大于4GB的文件大小?

11

我写了一个简单的函数,用于获取文件的大小。

int file_size( char * filename )
{
     int size;
     struct stat st;

     stat( filename, &st );
     size = st.st_size;

     return size;

}//file_size

这个代码能够正常工作,但是如果有一个文件的大小超过4GB,那么我会得到一个负数返回,而这显然不是正确的文件大小。那么我该如何获得如此大的文件大小呢?我认为返回值应该是一些其他的东西,比如int,但我不知道具体是什么,而且我也不认为这会解决我的问题。

谢谢,

kampi

更新:

嗨!

我找到了解决方法。我必须使用 __stat64。我修改了我的函数,现在它能够检索真正的文件大小。我用一个8GB的大文件测试了一下。

unsigned long long int file_size( char * filename )
{
    unsigned long long int size;
    struct __stat64 st;

    __stat64( filename, &st );
    size = st.st_size;

   return size;

}//file_size

还有一个注意事项:

当我使用printf时,必须使用"%I64d"才能打印出它。


如果您将 int 更改为 off_t,或者如果不可用,则更改为 size_t,那会怎样呢?这两种情况都适用于 size 的返回类型和声明。 - Alok Singhal
5个回答

5
您可以使用 Win32 的 GetFileSizeEx 函数。
HANDLE aFile = CreateFile
(
  filename,
  FILE_READ_ATTRIBUTES,
  0,
  NULL,
  OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL,
  NULL
);

if (aFile != INVALID_HANDLE_VALUE)
{
  long long aSize;
  GetFileSizeEx(aFile, &aSize);

  CloseHandle(aFile);
  return aSize;
}
else
  return -1;

这可能存在一个小问题(不是很确定),就是在同一进程中混合使用posix调用和win32调用可能会比较困难。看起来,问问题的人可能来自unix背景,并且只想使用posix调用。 - Aryabhatta

5

非常感谢,这是解决我的问题最简单的方法。 - kampi

2

st_size 在 wchar.h 中被定义为 long,因此您可以尝试使用 long 而不是 int。

struct stat {
    ....
    _off_t     st_size;
    ....
}

....

typedef long _off_t;  

也许可以像这样
long file_size( char * filename )
{
     long size;
     struct stat st;

     stat( filename, &st );
     size = st.st_size;

     return size;

}//file_size

1
没有理由不能在文件大小上加上 "unsigned",因为文件大小不太可能是负数。 - user257111
2
如果在st.st_size中发生截断,我很好奇将其分配给long类型如何在这种情况下有所帮助。 - Arun

2
在这种情况下,stat() 的返回值可能是-1,并且errno被设置为EOVERFLOW
我的(64位x86机器)stat的手册上写道:

EOVERFLOW

(stat())路径指向的文件大小无法用类型off_t表示。当在32位平台上编译应用程序而没有使用-D_FILE_OFFSET_BITS=64选项时,在文件大小超过(2<<31)-1位的文件上调用stat()时会发生这种情况。


0

我认为问题是由于文件大小超过了INT_MAX,因此它会给你负值。

可能你可以对长数据类型进行类型转换,这可能有效。

否则使用fseek,ftell函数。然后从起始文件指针减去结束文件指针。它也会给你文件大小(字节数)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接