2009-08-07 113 views
28

我正在重構一些舊的代碼,並遇到以下代碼行將字節轉換爲GB。在C#中將字節轉換爲GB?

decimal GB = KB/1024/1024/1024; 

有沒有更好的方法來重構下面的一段代碼?

更新

我的意思是說字節千兆字節。我給了錯誤的信息。

+14

'小數GB = KB/1024/1024;'將要更好...... – sth 2009-08-07 00:31:00

+9

除了額外的劃分之外,代碼的寫法沒有問題;它的意圖非常清楚,沒有不必要的冗長,並且沒有性能問題。你爲什麼要重構它? – 2009-08-07 00:35:52

+1

我認爲這很好,但我可能會GB =字節* 1E-9; – kenny 2010-01-17 22:28:17

回答

18

如果準確的精度並不重要,使用雙:

double gb = kb/1048576D 

與帕維爾在這裏同意 - 有沒有真正的任何需要重構的代碼......其實,如果這是在你的代碼庫的最大問題,我想你可能會坐在有史以來最好的軟件上。

+2

+ 1對使用雙重,但我認爲原來執行的意圖更清晰。 – Marc 2009-08-07 00:40:28

+1

@Marc可能。我認爲gb = kb ...部分是一個很好的線索:) – 2009-08-07 00:41:59

+0

你可以通過聲明一個常量來提高值1048576的可讀性,這個意圖揭示了一個名字...... – mezoid 2009-08-15 00:52:45

2

就我個人而言,我會這樣寫:decimal GB = KB/(1024 * 1024);,但確實沒有必要重寫代碼。

7

原始代碼簡潔,易於閱讀,並具有合理的變量名稱,自我記錄;我不會改變它。

如果你絕對必須重構,你可以創建上的數字類型的一組擴展方法:

public static double BytesToKilobytes(this Int32 bytes) 
{ 
    return bytes/1024d; 
} 
public static double BytesToMegabytes(this Int32 bytes) 
{ 
    return bytes/1024d/1024d; 
} 
public static double KilobytesToBytes(this double kilobytes) 
{ 
    return kilobytes * 1024d; 
} 

//You can then do something like: 
double filesize = 32.5d; 
double bytes = filesize.KilobytesToBytes(); 

但是,除非你的代碼做幾乎沒有,但字節轉換爲千字節等等,這一切真的會做的是混亂了Intellisense沒有真正的收益。

2

那麼,公式是錯誤的(在千兆字節中只有大約一百萬千字節,而不是千萬字節),但除此之外,沒關係。任何以前使用這些號碼的人都會知道它的含義。

我會注意的一件事(我不知道這是否是C#的問題)是如果x不是基本類型,編譯器可能無法優化x/1024/1024。使用C和整數,編譯器可以很容易地將其轉換爲「盲目快速移位 - 右乘20位」指令。

如果十進制是一個類而不是基本類型,編譯器可能不得不做兩個除法操作。這是否對速度有任何實際影響(或者甚至是否真的發生)都超出了我的知識領域。

我會考慮改變的一件事是實際的變量名稱。它對編譯代碼並沒有真正的區別,但我更喜歡較長的變量名稱而不是縮寫,所以我會選擇kiloBytes/gigaBytes或類似的東西。根據您的編碼標準,KB/GB太容易與常量混淆。

+0

decimal是一個內置的類型,而不是類。但它也不支持bitshifts,即使它們有意義。也許編譯器可以在這種情況下使用它們,即使程序員不能。 – 2014-08-20 03:15:13

1

爲了確保預編譯計算除數:

decimal GB = KB/(1024 * 1024); 

請注意,您在實際計算吉布(gibibyte),而不是GB(千兆字節)。如果你真的想計算國標,那將是:

decimal GB = KB/(1000 * 1000); 
+1

在一般用法中,千兆字節用於表示1024^3字節,兆字節表示1024^2,千字節表示1024.它在技術上可能不正確,但我不認爲這裏有任何人(其他人)會介意。 – snarf 2009-08-07 01:30:23

+0

是的,大多數人都沒有意識到標準事件,儘管它已經存在了十年以上,這就是爲什麼我對它做了一個說明...... – Guffa 2009-08-07 07:14:38

+0

「標準」只是沒有真正的標準事件,因爲它改變了常見的意義爲常見的事物創造新詞。這就是爲什麼沒有人接受這個標準,來自行業制定的標準。 – 2009-08-08 13:42:49

1

理論上,這是更快的(預計算常數做乘法而不是除法)。它可能沒有足夠重要,但以防萬一。

double const KbToGbFactor = 1d/1024 /1024; 

double gb = kb * KbToGbFactor; 
+1

我非常肯定這將在程序編譯時進行優化。不管你是否想要一個const在這裏,這更多的是品味的問題。 – Spoike 2010-01-17 22:29:37

+0

我不太確定 - http://blogs.msdn.com/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx – 2010-01-18 10:57:33

+0

我喜歡這個答案的「清晰度」 (在我看來),但不是用於「優化」。 Uhg :-) – 2010-10-21 06:21:19

80

我在這裏開發了這個方法,工作到結核病。

private static string FormatBytes(long bytes) 
{ 
    string[] Suffix = { "B", "KB", "MB", "GB", "TB" }; 
    int i; 
    double dblSByte = bytes; 
    for (i = 0; i < Suffix.Length && bytes >= 1024; i++, bytes /= 1024) 
    { 
     dblSByte = bytes/1024.0; 
    } 

    return String.Format("{0:0.##} {1}", dblSByte, Suffix[i]); 
} 
+3

有點從主題走了,但我喜歡這個把戲。 +1 – ktutnik 2011-09-25 01:41:58

+0

我同意@ktutnik關於第二部分! – Shimmy 2012-12-20 10:36:33

+0

這是如何工作的?你在if/else中缺少返回類型 – Kimtho6 2013-08-07 10:22:32

3
/// <summary> 
/// Function to convert the given bytes to either Kilobyte, Megabyte, or Gigabyte 
/// </summary> 
/// <param name="bytes">Double -> Total bytes to be converted</param> 
/// <param name="type">String -> Type of conversion to perform</param> 
/// <returns>Int32 -> Converted bytes</returns> 
/// <remarks></remarks> 
public static double ConvertSize(double bytes, string type) 
{ 
    try 
    { 
     const int CONVERSION_VALUE = 1024; 
     //determine what conversion they want 
     switch (type) 
     { 
      case "BY": 
       //convert to bytes (default) 
       return bytes; 
      case "KB": 
       //convert to kilobytes 
       return (bytes/CONVERSION_VALUE); 
      case "MB": 
       //convert to megabytes 
       return (bytes/CalculateSquare(CONVERSION_VALUE)); 
      case "GB": 
       //convert to gigabytes 
       return (bytes/CalculateCube(CONVERSION_VALUE)); 
      default: 
       //default 
       return bytes; 
      } 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
     return 0; 
     } 
} 

/// <summary> 
/// Function to calculate the square of the provided number 
/// </summary> 
/// <param name="number">Int32 -> Number to be squared</param> 
/// <returns>Double -> THe provided number squared</returns> 
/// <remarks></remarks> 
public static double CalculateSquare(Int32 number) 
{ 
    return Math.Pow(number, 2); 
} 


/// <summary> 
/// Function to calculate the cube of the provided number 
/// </summary> 
/// <param name="number">Int32 -> Number to be cubed</param> 
/// <returns>Double -> THe provided number cubed</returns> 
/// <remarks></remarks> 
public static double CalculateCube(Int32 number) 
{ 
    return Math.Pow(number, 3); 
} 

//Sample Useage 
String Size = "File is " + ConvertSize(250222,"MB") + " Megabytes in size" 
1

我需要它周圍的其他方法,從在詞語第三方組件文字大小轉換(例如,「0字節」,「1.1 MB」)轉換成通用的大小以字節計。所以我用這種方式:

 private static long UnformatBytes(string sizeInWords) 
    { 
     if(string.IsNullOrWhiteSpace(sizeInWords)) 
      return -1; 

     string size = sizeInWords.Split(' ').FirstOrDefault(); 
     double result; 
     if (string.IsNullOrWhiteSpace(size) || !double.TryParse(size, out result)) 
     { 
      Debugger.Break(); 
      return -1; 
     } 

     int pow; 

     if (sizeInWords.IndexOf("byte", StringComparison.OrdinalIgnoreCase) > -1) 
      pow = 0; 
     else if (sizeInWords.IndexOf("kb", StringComparison.OrdinalIgnoreCase) > -1) 
      pow = 1; 
     else if (sizeInWords.IndexOf("mb", StringComparison.OrdinalIgnoreCase) > -1) 
      pow = 2; 
     else if (sizeInWords.IndexOf("gb", StringComparison.OrdinalIgnoreCase) > -1) 
      pow = 3; 
     else if (sizeInWords.IndexOf("tb", StringComparison.OrdinalIgnoreCase) > -1) 
      pow = 4; 
     else 
      return -1; 

     return System.Convert.ToInt64((result * Math.Pow(1024, pow))); 
    } 
2

我寫了一個小工具類執行單位之間的轉換,心連心..

#region StorageDifferential 
/// <summary> 
/// Converts between Base 2 or Base 10 storage units [TB, GB, MB, KB, Bytes] 
/// </summary> 
public enum Differential : int 
{ 
    /// <summary> 
    /// Convert Bytes to Kilobytes 
    /// </summary> 
    ByteToKilo, 
    /// <summary> 
    /// Convert Bytes to Megabytes 
    /// </summary> 
    ByteToMega, 
    /// <summary> 
    /// Convert Bytes to Gigabytes 
    /// </summary> 
    ByteToGiga, 
    /// <summary> 
    /// Convert Bytes to Teraytes 
    /// </summary> 
    ByteToTera, 
    /// <summary> 
    /// Convert Kilobytes to Bytes 
    /// </summary> 
    KiloToByte, 
    /// <summary> 
    /// Convert Kilobytes to Megabytes 
    /// </summary> 
    KiloToMega, 
    /// <summary> 
    /// Convert Kilobytes to Gigabytes 
    /// </summary> 
    KiloToGiga, 
    /// <summary> 
    /// Convert Kilobytes to Terabytes 
    /// </summary> 
    KiloToTera, 
    /// <summary> 
    /// Convert Megabytes to Bytes 
    /// </summary> 
    MegaToByte, 
    /// <summary> 
    /// Convert Megabytes to Kilobytes 
    /// </summary> 
    MegaToKilo, 
    /// <summary> 
    /// Convert Megabytes to Gigabytes 
    /// </summary> 
    MegaToGiga, 
    /// <summary> 
    /// Convert Megabytes to Terabytes 
    /// </summary> 
    MegaToTera, 
    /// <summary> 
    /// Convert Gigabytes to Bytes 
    /// </summary> 
    GigaToByte, 
    /// <summary> 
    /// Convert Gigabytes to Kilobytes 
    /// </summary> 
    GigaToKilo, 
    /// <summary> 
    /// Convert Gigabytes to Megabytes 
    /// </summary> 
    GigaToMega, 
    /// <summary> 
    /// Convert Gigabytes to Terabytes 
    /// </summary> 
    GigaToTerra, 
    /// <summary> 
    /// Convert Terabyte to Bytes 
    /// </summary> 
    TeraToByte, 
    /// <summary> 
    /// Convert Terabyte to Kilobytes 
    /// </summary> 
    TeraToKilo, 
    /// <summary> 
    /// Convert Terabytes to Megabytes 
    /// </summary> 
    TeraToMega, 
    /// <summary> 
    /// Convert Terabytes to Gigabytes 
    /// </summary> 
    TeraToGiga, 
} 
#endregion 

#region Storage Sizes 
/// <summary> 
/// Enumeration of recognized storage sizes [in Bytes] 
/// </summary> 
public enum StorageSizes : long 
{ 
    /// <summary> 
    /// Base 10 Conversion 
    /// </summary> 
    KILOBYTE = 1000, 
    MEGABYTE = 1000000, 
    GIGABYTE = 1000000000, 
    TERABYTE = 1000000000000, 
    /// <summary> 
    /// Base 2 Conversion 
    /// </summary> 
    KIBIBYTE = 1024, 
    MEBIBYTE = 1048576, 
    GIBIBYTE = 1073741824, 
    TEBIBYTE = 1099511627776, 
} 
#endregion 

#region StorageBase 
/// <summary> 
/// Storage powers 10 based or 1024 based 
/// </summary> 
public enum StorageBase : int 
{ 
    /// <summary> 
    /// 1024 Base power, Typically used in memory measurements 
    /// </summary> 
    BASE2, 
    /// <summary> 
    /// 10 Base power, Used in storage mediums like harddrives 
    /// </summary> 
    BASE10, 
} 
#endregion 

/// <summary> 
/// Convert between base 1024 storage units [TB, GB, MB, KB, Byte] 
/// </summary> 
public static class StorageConverter 
{ 
    /// <summary> 
    /// Convert between base 1024 storage units [TB, GB, MB, KB, Byte] 
    /// </summary> 
    /// <param name="SizeDifferential">Storage conversion differential [enum]</param> 
    /// <param name="UnitSize">Size as mutiple of unit type units [double]</param> 
    /// <param name="BaseUnit">Size of the base power [enum]</param> 
    /// <returns>Converted unit size [double]</returns> 
    public static double Convert(Differential SizeDifferential, double UnitSize, StorageBase BaseUnit = StorageBase.BASE10) 
    { 
     if (UnitSize < 0.000000000001) return 0; 

     double POWER1 = 1000; 
     double POWER2 = 1000000; 
     double POWER3 = 1000000000; 
     double POWER4 = 1000000000000; 

     if (BaseUnit == StorageBase.BASE2) 
     { 
      POWER1 = 1024; 
      POWER2 = 1048576; 
      POWER3 = 1073741824; 
      POWER4 = 1099511627776; 
     } 

     switch (SizeDifferential) 
     { 
      case Differential.ByteToKilo: 
       return UnitSize/POWER1; 
      case Differential.ByteToMega: 
       return UnitSize/POWER2; 
      case Differential.ByteToGiga: 
       return UnitSize/POWER3; 
      case Differential.ByteToTera: 
       return UnitSize/POWER4; 
      case Differential.KiloToByte: 
       return UnitSize * POWER1; 
      case Differential.KiloToMega: 
       return UnitSize/POWER1; 
      case Differential.KiloToGiga: 
       return UnitSize/POWER2; 
      case Differential.KiloToTera: 
       return UnitSize/POWER3; 
      case Differential.MegaToByte: 
       return UnitSize * POWER2; 
      case Differential.MegaToKilo: 
       return UnitSize * POWER1; 
      case Differential.MegaToGiga: 
       return UnitSize/POWER1; 
      case Differential.MegaToTera: 
       return UnitSize/POWER2; 
      case Differential.GigaToByte: 
       return UnitSize * POWER3; 
      case Differential.GigaToKilo: 
       return UnitSize * POWER2; 
      case Differential.GigaToMega: 
       return UnitSize * POWER1; 
      case Differential.GigaToTerra: 
       return UnitSize/POWER1; 
      case Differential.TeraToByte: 
       return UnitSize * POWER4; 
      case Differential.TeraToKilo: 
       return UnitSize * POWER3; 
      case Differential.TeraToMega: 
       return UnitSize * POWER2; 
      case Differential.TeraToGiga: 
       return UnitSize * POWER1; 
     } 

     return 0; 
    } 
} 
0
public static string BytesToString(this long bytes, string format = "#,##0.00") { 
     var unitstr = new string[] { "B", "KB", "MB", "GB", "TB" }; 
     var bytesd = Convert.ToDouble(bytes); 
     var unit = 0; 
     while (bytesd/1024D > 1 && unit < unitstr.Length) { 
      unit++; bytesd /= 1024D; 
     } 
     return string.Format("{0:" + format + "}{1}", bytesd, unitstr[unit]); 
    } 
0
#region AutoFileSize 
    public string AutoFileSize(long number) 
    { 
     double tmp = number; 
     string suffix = " B "; 
     if (tmp > 1024) { tmp = tmp/1024; suffix = " KB"; } 
     if (tmp > 1024) { tmp = tmp/1024; suffix = " MB"; } 
     if (tmp > 1024) { tmp = tmp/1024; suffix = " GB"; } 
     if (tmp > 1024) { tmp = tmp/1024; suffix = " TB"; } 
     return tmp.ToString("n") + suffix; 
    } 
    #endregion 

long number = (long)fu.PostedFile.ContentLength; 
1

這是很好的一個小改進JLopez的回答(請投票給他,不是我)。 在這裏,你可以選擇或不單位指示和公斤單元被寫入與小寫字母「K」(大寫一個爲開爾文)

//note: this is the JLopez answer!! 
/// <summary> 
/// Return size in human readable form 
/// </summary> 
/// <param name="bytes">Size in bytes</param> 
/// <param name="useUnit ">Includes measure unit (default: false)</param> 
/// <returns>Readable value</returns> 
public static string FormatBytes(long bytes, bool useUnit = false) 
    { 
     string[] Suffix = { " B", " kB", " MB", " GB", " TB" }; 
     double dblSByte = bytes; 
     int i; 
     for (i = 0; i < Suffix.Length && bytes >= 1024; i++, bytes /= 1024) 
     { 
      dblSByte = bytes/1024.0; 
     } 
     return $"{dblSByte:0.##}{(useUnit ? Suffix[i] : null)}"; 
    }