3 回答

TA貢獻1836條經驗 獲得超13個贊
tl; dr
所有其他答案都關閉了:)
問題
我想在這個老問題上加上兩分錢,因為似乎有很多答案都非常相似,但在某些情況下得出的結果卻非常不準確。
要了解為什么我們首先必須定義文件夾的大小。以我的理解(可能是OP之一),它是目錄(包括其所有內容)在卷上使用的字節數?;蛘撸瑩Q一種說法:
如果目錄將被完全刪除,則該空間變為可用。
我知道,此定義不是解釋問題的唯一有效方法,但我確實認為這是大多數用例的根源。
錯誤
現有的答案都采用非常簡單的方法:遍歷目錄內容,增加(常規)文件的大小。這并沒有考慮到一些微妙之處。
卷上使用的空間以塊為單位遞增,而不是以字節為單位遞增。即使是一個字節的文件也至少使用一個塊。
文件包含元數據(如任意數量的擴展屬性)。此數據必須放在某處。
HFS部署文件系統壓縮,以實際使用較少的字節(而不是其實際長度)存儲文件。
解
所有這些原因使現有的答案產生不精確的結果。因此,我提議對此擴展NSFileManager(由于長度而在github 上的代碼:Swift 4,Objective C)來解決這個問題。它的速度也相當快,特別是對于包含大量文件的目錄。
該解決方案的核心是使用NSURL的NSURLTotalFileAllocatedSizeKey或NSURLFileAllocatedSizeKey性的判定來檢索文件的大小。
測試
我還建立了一個簡單的iOS測試項目,展示了解決方案之間的差異。它顯示了在某些情況下結果可能完全錯誤。
在測試中,我創建了一個包含100個小文件的目錄(范圍從0到800字節)。folderSize:從其他答案中復制的方法總共計算出21 kB,而我的allocatedSize方法得出的結果為401 kB。
證明
allocatedSize通過計算刪除測試目錄之前和之后卷上可用字節的差異,我確保的結果更接近正確的值。在我的測試中,差異始終等于的結果allocatedSize。
請參閱Rob Napier的評論,以了解仍有改進的空間。
性能
但是還有另一個優點:在計算包含1000個文件的目錄的大小時,在我的iPhone 6上,此folderSize:方法大約需要250毫秒,而allocatedSize在35毫秒內遍歷相同的層次結構。
這可能是由于使用NSFileManager的new(ish)enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:API遍歷了層次結構。通過此方法,您可以為要迭代的項目指定預取屬性,從而減少io。
結果
Test `folderSize` (100 test files)
size: 21 KB (21.368 bytes)
time: 0.055 s
actual bytes: 401 KB (401.408 bytes)
Test `allocatedSize` (100 test files)
size: 401 KB (401.408 bytes)
time: 0.048 s
actual bytes: 401 KB (401.408 bytes)
Test `folderSize` (1000 test files)
size: 2 MB (2.013.068 bytes)
time: 0.263 s
actual bytes: 4,1 MB (4.087.808 bytes)
Test `allocatedSize` (1000 test files)
size: 4,1 MB (4.087.808 bytes)
time: 0.034 s
actual bytes: 4,1 MB (4.087.808 bytes)

TA貢獻2037條經驗 獲得超6個贊
為亞歷克斯加油打氣,您已經提供了很多幫助,現在已經編寫了以下功能,可以發揮作用...
- (unsigned long long int)folderSize:(NSString *)folderPath {
NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
NSString *fileName;
unsigned long long int fileSize = 0;
while (fileName = [filesEnumerator nextObject]) {
NSDictionary *fileDictionary = [[NSFileManager defaultManager] fileAttributesAtPath:[folderPath stringByAppendingPathComponent:fileName] traverseLink:YES];
fileSize += [fileDictionary fileSize];
}
return fileSize;
}
它提供了與Finder一樣的確切字節數。
順便說一句,Finder返回兩個數字。一個是磁盤上的大小,另一個是實際的字節數。
例如,當我在一個文件夾中運行此代碼時,它以130398的“文件大小”返回代碼中。當我在Finder中簽入時,它說磁盤上的大小為201KB(130,398字節)。
有點不確定此處的實際大?。?01KB或130,398字節)?,F在,我會安全地將限制減少一半,直到我知道這到底意味著什么...
如果有人可以向這些不同的號碼添加更多信息,我將不勝感激。
干杯,
- 3 回答
- 0 關注
- 750 瀏覽