簡體   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