在windows中查找超过4gb的正确文件大小

Finding correct filesize over 4gb in windows

本文关键字:文件大小 4gb windows 查找      更新时间:2023-10-16

我已经用这个c++代码在windows中找到了一些文件的文件大小(使用visual studio(:

(p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

如果文件大于4gb,这不会给我正确的文件大小。经过一些研究,我尝试了:

(p_findFileData->nFileSizeHigh * (MAXDWORD+1)) + p_findFileData->nFileSizeLow); 

当我读到nflesizehigh和nflesizelow分别是文件大小的64位值中的32位时,如果文件大小值大于32位,我们将maxdword(在我的情况下为0xffffff(乘以nflesizeheight。第二个解决方案也不起作用,给了我一个比原来更小的尺寸。我再次尝试了这个:

ULONGLONG FileSize = (FindFileData.nFileSizeHigh * 4294967296) + FindFileData.nFileSizeLow;

它奏效了。此外,我还使用了另一种解决方案来获得文件大小:

 ULONGLONG FileSize = FindFileData.nFileSizeHigh;
 FileSize <<= sizeof( FindFileData.nFileSizeHigh ) *8; 
 FileSize |= FindFileData.nFileSizeLow;

上述解决方案也适用:

我想知道为什么前两个解决方案不起作用,如果可能的话,还想知道最后一个解决方案的解释,因为我想知道代码的内部工作情况。我们将不胜感激。

使用ULARGE_INTEGER结构来组合值,而不是尝试手动计算/移位它们:

ULARGE_INTEGER ul;
ul.HighPart = p_findFileData->nFileSizeHigh;
ul.LowPart = p_findFileData->nFileSizeLow;
ULONGLONG FileSize = ul.QuadPart;

我会使用:

ULONGLONG FileSize = (static_cast<ULONGLONG>(FindFileData.nFileSizeHigh) <<
                      sizeof(FindFileData.nFileSizeLow) *8) |
                     FindFileData.nFileSizeLow;

ULONGLONG的强制转换是必要的,以便在32位值进入FileSize变量之前将其转换为64位值。

当然,你也可以使用乘法,但它在任何特定方面都不会"更好",而且很可能会慢一点[在这种特殊情况下可能没有什么大不了的,但我认为使用乘法没有任何好处。

现在对于"不起作用"的变体:

即使这确实有效:

 (p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

你会得到错误的值,因为MAXDWORD比4GB小一个,所以你最终得到了错误的值[是的,它可能很接近,但它至少会错1个字节,可能更多]。然而,由于我们处理的是32位值,它实际上变成了:

 -p_findFileData->nFileSizeHigh + p_findFileData->nFileSizeLow;

因为MAXDWORD与-1相同(是的,它很可能是一个无符号值,但如果以这种方式使值溢出,它的行为与负符号值相同(。

这个在数学上是正确的,但由于它溢出了一个32位的值,所以不起作用。

 (p_findFileData->nFileSizeHigh * (MAXDWORD+1)) + p_findFileData->nFileSizeLow);

所以你得到了low part + (0 * high part),这当然是不正确的。

有了演员阵容,这将起作用:

 static_cast<ULONGLONG>(p_findFileData->nFileSizeHigh) * (MAXDWORD+1) +
 p_findFileData->nFileSizeLow;
(p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

这不会给出正确的结果,因为MAXDWORD是错误的值。

(p_findFileData->nFileSizeHigh * (MAXDWORD+1)) + p_findFileData->nFileSizeLow); 

这不起作用,因为在将类型强制转换为足够大的值之前,要将+1添加到MAXDWORD中。

(FindFileData.nFileSizeHigh * 4294967296) + FindFileData.nFileSizeLow;

这是因为4294967296是64位类型。

FileSize <<= sizeof( FindFileData.nFileSizeHigh ) *8; 
FileSize |= FindFileData.nFileSizeLow;

这是因为您将高位移位32(这与乘以4294967296相同(,然后使用按位或"相加"低位。

我遇到了完全相同的问题,答案对我的代码来说非常简单。只需将MAXDWORD强制转换为64位int(例如uint64_t(。这背后的解释可以从我在这里收到的答案中找到。