2009-08-07 24 views
28

Ich habe einige alten Code refactoring und kam über die folgende Codezeile, um Bytes in GB zu konvertieren.Konvertieren von Bytes in GB in C#?

decimal GB = KB/1024/1024/1024; 

Gibt es einen besseren Weg, um das folgende Stück Code Refactoring?

aktualisieren

bedeutete, dass ich Bytes zu Gigabytes sagen. Ich gab falsche Informationen.

+14

' dezimal GB = KB/1024/1024 wählen besser sein ... – sth

+9

Abgesehen von einer extra Division ist nichts falsch mit dem Code wie geschrieben; es ist vollkommen klar in seiner Absicht, nicht unnötig ausführlich, und es gibt keine Perf Probleme. Warum möchtest du es umgestalten? –

+1

Ich denke, es ist in Ordnung, obwohl ich wahrscheinlich GB = Bytes * 1E-9; – kenny

Antwort

18

Wenn genaue Präzision nicht wichtig ist, verwenden Sie doppelt:

double gb = kb/1048576D 

mit Pavel Zustimmen hier - es gibt wirklich keine Notwendigkeit, diesen Code Refactoring ... in der Tat, wenn dies das größte Problem in Ihrer Code-Basis ist Ich glaube, du sitzt vielleicht auf der am besten geschriebenen Software aller Zeiten.

+2

+1 auf die Verwendung von Doppel, aber ich denke, die ursprüngliche Umsetzung der Absicht ist klarer. – Marc

+1

@Marc wahrscheinlich. Ich denke, der gb = kb ... Teil ist ein ziemlich guter Anhaltspunkt :) :) –

+0

Sie könnten wahrscheinlich die Lesbarkeit des Wertes 1048576 verbessern, indem Sie es als eine Konstante mit einer Absicht enthüllt Namen ... – mezoid

2

Persönlich würde ich es so schreiben: decimal GB = KB/(1024 * 1024);, aber es gibt wirklich keine Notwendigkeit, den Code wie geschrieben zu refaktorieren.

7

Der ursprüngliche Code ist prägnant, leicht zu lesen und mit sinnvollen Variablennamen, selbstdokumentierend; Ich würde es nicht ändern.

Wenn Sie unbedingt Refactoring müssen Sie eine Reihe von Erweiterungsmethoden auf den numerischen Typen erstellen können:

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(); 

Aber es sei denn, Ihr Code tut so gut wie nichts, sondern konvertieren Bytes Kilobyte usw., all dies wird wirklich tun ist Durcheinander bringen Intellisense für keinen wirklichen Gewinn.

2

Nun, die Formel ist falsch (es gibt nur etwa eine Million Kilobyte in einem Gigabyte, nicht tausend Millionen), aber abgesehen davon ist es in Ordnung. Wer einmal mit diesen Zahlen gearbeitet hat, weiß, was es bedeutet.

Eine Sache, auf die ich achten würde (und ich weiß nicht, ob das ein Problem mit C# ist) ist, dass ein Compiler möglicherweise nicht in der Lage ist, x/1024/1024 zu optimieren, wenn x kein Basistyp ist. Mit C und ganzen Zahlen würde der Compiler dies ziemlich leicht in einen "blendend-schnell-shift-rechts-durch-20-Bits" Befehl umwandeln.

Wenn Dezimal eine Klasse und nicht ein Basistyp ist, muss der Compiler möglicherweise zwei Divisionsoperationen durchführen. Ob dies einen wirklichen Einfluss auf die Geschwindigkeit hat (oder auch nur, ob es überhaupt passiert), liegt außerhalb meines Wissensbereiches.

Eine Sache, die ich in Betracht ziehen würde, sind die tatsächlichen Variablennamen. Es macht keinen wirklichen Unterschied für den kompilierten Code, aber ich bevorzuge längere Variablennamen anstelle von Abkürzungen, also würde ich mich für kiloBytes/gigaBytes oder so ähnlich entscheiden. KB/GB ist zu leicht mit Konstanten zu verwechseln, abhängig von Ihren Codierungsstandards.

+0

Dezimal ist eine eingebaute Typ, keine Klasse. Aber Bitshifts werden auch nicht unterstützt, obwohl sie sinnvoll sind. Vielleicht kann der Compiler sie in diesem Szenario verwenden, obwohl der Programmierer das nicht kann. –

1

Um sicherzustellen, dass der Compiler vorab berechnet die Teilern:

decimal GB = KB/(1024 * 1024); 

Beachten Sie, dass Sie tatsächlich GiB (gibibyte), nicht GB (Gigabyte) sind zu berechnen. Wenn Sie wirklich GB berechnet werden soll, wäre das:

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

In der allgemeinen Verwendung wird Gigabyte verwendet, um 1024^3 Bytes, Mega für 1024^2, Kilo für 1024 zu bezeichnen. Es mag technisch nicht korrekt sein, aber ich glaube nicht, dass irgendjemand (anders) hier denkt. – snarf

+0

Ja, die meisten Leute sind sich des Standards nicht bewusst, obwohl es schon seit mehr als zehn Jahren existiert, deshalb habe ich eine Notiz darüber gemacht ... – Guffa

+0

Der "Standard" ist einfach kein echter, da er die üblichen Bedeutungen von die Wörter und schuf neue Wörter für allgemeine Sachen. Deshalb akzeptiert wirklich niemand diesen Standard, abgesehen von der Industrie, die es gemacht hat. –

1

Theoretisch dies schneller ist (precomputing die ständige Vermehrung zu tun, anstatt der Teilung). Es wird wahrscheinlich nicht oft genug verwendet, um eine Rolle zu spielen, aber nur für den Fall.

double const KbToGbFactor = 1d/1024 /1024; 

double gb = kb * KbToGbFactor; 
+1

Ich bin mir ziemlich sicher, dass dies optimiert wird, wenn das Programm kompiliert wird. Es ist eher eine Frage des Geschmacks, ob Sie hier eine Konstante wollen oder nicht. – Spoike

+0

Ich bin mir nicht so sicher - http://blogs.msdn.com/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx –

+0

Ich mag diese Antwort für "clarity" (in meinen Gedanken), aber nicht für "Optimierung". Uhg :-) –

80

Ich habe diese Methode hier entwickelt, funktioniert bis TB.

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

ein bisschen weit weg vom Thema, aber ich liebe den Trick. +1 – ktutnik

+0

Ich stimme @ktutnik über den zweiten Teil zu! – Shimmy

+0

Wie funktioniert das? Du verpasst einen Rückgabetyp in der if/else – Kimtho6

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

ich brauchte es umgekehrt, von 3rd-Party-Komponente wörtliche Größe in Worten (beispielsweise "0 Byte", "1.1 MB") in generische Größe in Bytes konvertieren. so habe ich es so:

 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

ich eine kleine Utility-Klasse geschrieben, die Konvertierungen zwischen Einheiten führt, hth ..

#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

Dies ist eine geringe Verbesserung der guten JLopez 'Antwort (bitte stimme ihm zu, nicht ich). `Würden; Hier können Sie mit dem kleinen„k“haben oder nicht die Einheiten Anzeige und die Kilo-Einheit geschrieben (die Großbuchstaben sind für Kelvin)

//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)}"; 
    } 
Verwandte Themen