<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
直接貼程式碼吧
/// <summary> /// 格式化檔案大小 /// </summary> /// <param name="filesize">檔案傳入大小</param> /// <returns></returns> private static string GetFileSize(long filesize) { try { if (filesize < 0) { return "0"; } else if (filesize >= 1024 * 1024 * 1024) //檔案大小大於或等於1024MB { return string.Format("{0:0.00} GB", (double)filesize / (1024 * 1024 * 1024)); } else if (filesize >= 1024 * 1024) //檔案大小大於或等於1024KB { return string.Format("{0:0.00} MB", (double)filesize / (1024 * 1024)); } else if (filesize >= 1024) //檔案大小大於等於1024bytes { return string.Format("{0:0.00} KB", (double)filesize / 1024); } else { return string.Format("{0:0.00} bytes", filesize); } } catch (Exception ex) { throw ex; } }
上述程式碼是將檔案大小格式化為我們想要的大小。
FileInfo t = new FileInfo(filePath);//獲取檔案 檔案大小 = GetFileSize(t.Length);//這樣我們就獲取到了檔案的大小
先說一下為什麼要用這種極其麻煩的方法來判斷檔案的佔用空間,因為找不到簡單的方法。
如果是想算資料夾的佔用空間,只需要將裡面的檔案的佔用空間加在一起就可以了。
這與是硬碟分割區格式有關。
大小是檔案的實際大小,而佔用空間是佔硬碟的實際空間,以FAT32格式為例,硬碟的基本儲存單位是簇,在FAT32中一簇是4KB 那麼,也就是說即使檔案只有1個位元組,在硬碟上也要佔到4KB的空間 如果檔案是4KB零1個位元組,那就要佔用8KB的空間,以此類推 結論: 大小是檔案的實際大小,而佔用空間是佔硬碟的實際空間。
如圖(我這裡一簇是4kB)
所以,要想獲得佔用空間,就需要先獲得檔案的大小,然後就可以通過把簇補全即可算出檔案的佔用空間。而獲取檔案大小的方法很簡單,其程式碼如下。
FileInfo fileInfo = new FileInfo(filePath); Console.WriteLine(fileInfo.Length);
但是通過這種方法計算出的資料並不準確
為什麼會不準確呢?因為有很多不正常的檔案,那些檔案的大小是大於檔案佔用空間的,例如:
而這種情況通過上面的那一段程式碼求出的檔案大小為23677位元組,然後補全簇之後得出的結果一定是大於檔案大小的,怎麼也不可能得出8192位元組(8KB),所以,通過這種方法得出的結果是不準確的。
為什麼會出現這種情況?根據硬碟儲存空間的規則可以得出,佔用空間一定是比其檔案大小要大的。那麼,只有一種可能,那就是該大小並不是檔案的實際大小,它是假的(也有可能是檔案管理系統中的某個未知的壓縮功能導致的)。
要想獲取一個檔案的實際大小,需要呼叫底層的windows API,這些api都是通過C++來編寫的。
裡面就有一個可以用來獲取檔案的實際大小:GetCompressedFileSize()方法。
該方法的說明檔案如下:(為什麼裡面的方法名多了個A,我也不知道為什麼,反正可以拿來用)
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getcompressedfilesizea
所以獲取檔案實際大小的方法如下:
static void Main(string[] args) { string name = @"D:Documentstest.zip"; //用來獲取高位數位(只有在讀取超過4GB的檔案才需要用到該引數) uint h = 0; //用來獲取低位資料 uint l = GetCompressedFileSize(name, ref h); //將兩個int32拼接成一個int64 ulong r = ((ulong)h << 32) + l; FileInfo fileInfo = new FileInfo(name); Console.WriteLine(fileInfo.Length); Console.WriteLine(h); Console.WriteLine(l); //最終結果 Console.WriteLine(r); Console.ReadKey(true); } [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] private static extern uint GetCompressedFileSize(string fileName, ref uint fileSizeHigh);
然後拿一個正常的檔案測試一下
可以看出,位元組數是正確的,然後再加上補全簇的演演算法,一切就正常了。
其程式碼如下:
static void Main(string[] args) { string name = @"C:WindowsDiagTrackGetFileActionAllowedList.dat"; //string name = @"D:Documentstest.zip"; uint h = 0; uint l = GetCompressedFileSize(name, ref h); ulong r = ((ulong)h << 32) + l; FileInfo fileInfo = new FileInfo(name); Console.WriteLine(fileInfo.Length); Console.WriteLine(h); Console.WriteLine(l); Console.WriteLine(r); ulong size = GetClusterSize("D:\"); if (r%size != 0) { decimal res = r / size; uint clu = (uint)Convert.ToInt32(Math.Ceiling(res)) + 1; r = size * clu; } //最終結果 Console.WriteLine(r); Console.ReadKey(true); } //獲取每簇的位元組數 private static uint GetClusterSize(string rootPath) { //提前宣告各項引數 uint sectorsPerCluster = 0, bytesPerSector = 0, numberOfFreeClusters = 0, totalNumberOfClusters = 0; GetDiskFreeSpace(rootPath, ref sectorsPerCluster, ref bytesPerSector, ref numberOfFreeClusters, ref totalNumberOfClusters); return bytesPerSector * sectorsPerCluster; } //用於獲取檔案實際大小的api [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] private static extern uint GetCompressedFileSize(string fileName, ref uint fileSizeHigh); //用於獲取盤資訊的api [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool GetDiskFreeSpace([MarshalAs(UnmanagedType.LPTStr)]string rootPathName, ref uint sectorsPerCluster, ref uint bytesPerSector, ref uint numberOfFreeClusters, ref uint totalNumbeOfClusters);
最後再看一下那個不正常的檔案:
結果8192位元組,計算成功。
。。。
。。。
。。。
這個C#也太坑了吧,為了弄一個獲取佔用空間,我搞了整整一整天。也不知道微軟怎麼想的,就不能直接給一個獲取佔用空間方法嗎?非地讓我們自己算,哎。
有時間為上面的程式碼加了一點說明,同時也加上了錯誤處理,修改後的程式碼如下:
using System; using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; namespace ConsoleApp1 { class Program { static void Main(string[] args) { string name = @"目標資料夾路徑"; uint h = 0; uint l = GetCompressedFileSize(name, ref h); if (l == uint.MaxValue) throw new IOException("檔案讀取失敗。", new Win32Exception(Marshal.GetLastWin32Error())); ulong r = ((ulong)h << 32) + l; FileInfo fileInfo = new FileInfo(name); Console.WriteLine("檔案大小:"); Console.WriteLine(fileInfo.Length); Console.WriteLine("高位資料:"); Console.WriteLine(h); Console.WriteLine("低位資料:"); Console.WriteLine(l); Console.WriteLine("檔案實際大小:"); Console.WriteLine(r); ulong size = GetClusterSize("D:\"); if (r % size != 0) { decimal res = r / size; uint clu = (uint)Convert.ToInt32(Math.Ceiling(res)) + 1; r = size * clu; } //最終結果 Console.WriteLine("檔案佔用空間:"); Console.WriteLine(r); Console.ReadKey(true); } //獲取每簇的位元組數 private static uint GetClusterSize(string rootPath) { //提前宣告各項引數 uint sectorsPerCluster = 0, bytesPerSector = 0, numberOfFreeClusters = 0, totalNumberOfClusters = 0; GetDiskFreeSpace(rootPath, ref sectorsPerCluster, ref bytesPerSector, ref numberOfFreeClusters, ref totalNumberOfClusters); return bytesPerSector * sectorsPerCluster; } //用於獲取檔案實際大小的api [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern uint GetCompressedFileSize(string fileName, ref uint fileSizeHigh); //用於獲取盤資訊的api [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool GetDiskFreeSpace([MarshalAs(UnmanagedType.LPTStr)]string rootPathName, ref uint sectorsPerCluster, ref uint bytesPerSector, ref uint numberOfFreeClusters, ref uint totalNumbeOfClusters); } }
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45