繁体   English   中英

在Windows中找到超过4GB的正确文件大小

[英]Finding correct filesize over 4gb in windows

我已经使用此C ++代码在Windows中找到某些文件的文件大小(使用Visual Studio):

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

如果文件大于4gb,这不能为我提供正确的文件大小。 经过一些研究,我尝试:

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

当我读到nfilesizehigh和nfilesizelow是32位时,分别是文件大小的64位值,如果文件大小值大于32位,则将maxdword(在我的情况下为0xffffffff)乘以nfilesizehigh。 第二种解决方案也不起作用,并且给我的尺寸比原来的小。 我再次尝试:

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

而且有效。 另外,我还使用了另一种解决方案来获取文件大小:

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

上述解决方案也适用:

我想知道为什么前两个解决方案不起作用,还想知道最后一个解决方案的解释,因为我想知道代码的内部工作原理。 帮助将不胜感激。

我会用:

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

在将32位值转换为FileSize变量之前,必须将其转换为ULONGLONG。

您当然也可以使用乘法-但这并不能以任何特定的方式“更好”,而且很有可能会稍微慢一点[在这种情况下可能没什么大不了,但是使用乘法我没有看到任何好处。

现在,针对“无效”变体:

即使这样做有效:

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

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

 -p_findFileData->nFileSizeHigh + p_findFileData->nFileSizeLow;

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

这在数学上是正确的,但是由于它溢出了32位值而无法正常工作。

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

因此,您得到的low part + (0 * high part)当然是不正确的。

使用cast,这将起作用:

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

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

ULARGE_INTEGER ul;
ul.HighPart = p_findFileData->nFileSizeHigh;
ul.LowPart = p_findFileData->nFileSizeLow;
ULONGLONG FileSize = ul.QuadPart;
(p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

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

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

这是行不通的,因为在将类型强制转换为足以容纳该值的值之前,您要向MAXDWORD添加+1。

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

这是因为4294967296是64位类型。

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

之所以有效,是因为您将高位移位了32位(这等于乘以4294967296),然后使用按位或将低位“相加”。

我遇到了完全相同的问题,对于我的代码来说答案很简单。 只需将MAXD​​WORD转换为64位int(例如uint64_t)。 可以在我在此处收到的答案中找到其背后的解释。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM