mxwawaawxm 发表于 2022-8-9 13:15

C语言GetFileAttributesEx函数获取文件大小的疑惑

本帖最后由 mxwawaawxm 于 2022-8-10 20:39 编辑

GetFileAttributesEx函数返回一个WIN32_FILE_ATTRIBUTE_DATA的结构体,
其中nFileSizeHigh是文件长度的高32位,nFileSizeLow是文件长度的低32位
所以文件的大小,按道理,应该是先让nFileSizeHigh先按位左移32位,再加上nFileSizeLow,就得到文件的大小。
但我在一本书中看到如下代码
定义变量ULONGLONG FileSize = nFileSizeHigh
然后FileSize <<= sizeof(WORD)*8;最后再加上nFileSizeLow,得到文件大小。
但奇怪的是,我打印了sizeof(WORD)*8的值,只移了16位,这是写错了吗。
我把FileSize <<= sizeof(WORD)*8;换成FileSize <<= 32;
两者数值是一样的
文件大小的数值依然对,是不是因为nFileSizeHigh都是0,所以移多少位,最后相加的数值都不变。
请大佬们帮忙看看。谢谢。

截图如下
代码如下
#include <windows.h>
#include <tchar.h>

void ByteToKMGT1(ULONGLONG FileSize);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, INT iCmdShow)
{
    WIN32_FILE_ATTRIBUTE_DATA FileInfo;
    PCTSTR pFileName = "d:\\ebooks\\辞典\\辞源第三版.pdf";
    ULONGLONG FileSize;

    if (GetFileAttributesEx(pFileName, GetFileExInfoStandard, &FileInfo)) {
      _tprintf(TEXT("nFileSizeHigh:\t%lu 字节\n"), FileInfo.nFileSizeHigh);
      _tprintf(TEXT("nFileSizeLow:\t%lu 字节\n"), FileInfo.nFileSizeLow);
      
      FileSize = FileInfo.nFileSizeHigh;
      // FileSize <<= 32;
      FileSize <<= sizeof(WORD)*8;
      _tprintf(TEXT("sizeof(WORD) * 8 = %I64u * 8 = %I64u\n"), sizeof(WORD), sizeof(WORD) * 8);
      FileSize += FileInfo.nFileSizeLow;
      _tprintf(TEXT("文件大小为:\t%I64u 字节\n"), FileSize);
      ByteToKMGT1(FileSize);
    }

    return 0;
}


/* 把字节动态转换为KB、MB、GB、TB */
void ByteToKMGT1(ULONGLONG FileSize)
{
    ULONGLONG Temp = FileSize;
    // 统计换算1024的次数
    int iCnt = 0;

    while (Temp>=1024) {
      Temp /= 1024;
      iCnt++;
    }

    switch (iCnt) {
      case 0:
            _tprintf(TEXT("共计 %d B\n"), (int)FileSize);
            break;
      case 1:
            _tprintf(TEXT("共计 %.4f KB\n"), FileSize/(float)1024);
            break;
      case 2:
            _tprintf(TEXT("共计 %.4f MB\n"), FileSize/((float)1024*1024));
            break;
      case 3:
            _tprintf(TEXT("共计 %.4f GB\n"), FileSize/((float)1024*1024*1024));
            break;
      case 4:
            _tprintf(TEXT("共计 %.4f TB\n"), FileSize/((float)1024*1024*1024*1024));
            break;
      default :
            break;            
    }
}

高苗苗 发表于 2022-8-9 14:25

拿程序找个超过3G的文件试下

Eaglecad 发表于 2022-8-9 15:39

FileInfo.nFileSizeHigh 本身就是0 左移 还是0。只有非0时,左移右移才会发生值的变化。
最简单的是你把 FileSize= 1;然后再FileSize <<= 32; 值就变了 4294967296。

iawyxkdn8 发表于 2022-8-9 16:16

拿程序找个超过8G的文件试下

clivia001 发表于 2022-8-9 16:54

sizeof(WORD)*8=2*8
图片不是写的很清楚吗

葡萄 发表于 2022-8-9 19:07

不错,但是看不见

mxwawaawxm 发表于 2022-8-9 21:37

高苗苗 发表于 2022-8-9 14:25
拿程序找个超过3G的文件试下

我找了个3.8G的文件试了一下。
nFileSizeHigh还是0
即便不移位,也是能得到正确大小

mxwawaawxm 发表于 2022-8-9 21:39

clivia001 发表于 2022-8-9 16:54
sizeof(WORD)*8=2*8
图片不是写的很清楚吗

我是好奇FileSize <<= sizeof(WORD)*8
这样移16位,是不是写错了。
因为nFileSizeHigh是文件长度的高32位,nFileSizeLow是文件长度的低32位
这样照道理来说,不是要移32位吗。

高苗苗 发表于 2022-8-10 09:09

mxwawaawxm 发表于 2022-8-9 21:37
我找了个3.8G的文件试了一下。
nFileSizeHigh还是0
即便不移位,也是能得到正确大小

我搞错了,昨天没注意,UINT32最长能表达4GB的长度,所以,应该是找个超过4G的文件试下

mxwawaawxm 发表于 2022-8-10 20:06

本帖最后由 mxwawaawxm 于 2022-8-10 22:24 编辑

高苗苗 发表于 2022-8-10 09:09
我搞错了,昨天没注意,UINT32最长能表达4GB的长度,所以,应该是找个超过4G的文件试下
谢谢。找了个6GB的文件测试。证明这样移位是错的

`FileSize <<= sizeof(WORD)*8;`

只移了16位,得这样写`FileSize <<= 32;`才能得到文件的正确大小。

页: [1]
查看完整版本: C语言GetFileAttributesEx函数获取文件大小的疑惑