Подтвердить что ты не робот

Преобразование байтов в GB в С#?

Я пересматривал старый код и набрал следующую строку кода для преобразования байтов в GB.

decimal GB = KB / 1024 / 1024 / 1024;

Есть ли лучший способ реорганизовать следующий фрагмент кода?

Update

Я хотел сказать байты в Gigabytes. Я дал неверную информацию.

4b9b3361

Ответ 1

Я разработал этот метод здесь, работает до ТБ.

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]);
}

Ответ 2

Если точность не важна, используйте double:

double gb = kb / 1048576D

Согласитесь с Павлом здесь - на самом деле нет необходимости реорганизовывать этот код... на самом деле, если это самая большая проблема в вашей кодовой базе, я думаю, вы могли бы сидеть на самом хорошо написанном программном обеспечении.

Ответ 3

Исходный код является кратким, легко читаемым и с разумными именами переменных, самодокументирующими; Я бы не изменил его.

Если вам абсолютно необходим рефакторинг, вы можете создать набор методов расширения для числовых типов:

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 без реального выигрыша.

Ответ 4

    /// <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"

Ответ 5

Лично я бы написал это следующим образом: decimal GB = KB / (1024 * 1024);, но нет необходимости реорганизовать код как написанный.

Ответ 6

Ну, формула неправильная (там всего около миллиона килобайт в гигабайте, а не тысяча миллионов), но, кроме этого, это нормально. Любой, кто привык работать с этими числами, будет знать, что это значит.

Одна вещь, о которой я бы подумал (и я не знаю, является ли это проблемой с С#), заключается в том, что компилятор не может оптимизировать x/1024/1024, если x не является базовым типом. С C и целыми числами компилятор довольно легко превратит это в инструкцию "blindingly-fast-shift-right-by-20-bits".

Если decimal является классом, а не базовым типом, компилятору, возможно, придется выполнять две операции деления. Независимо от того, имеет ли это какое-либо реальное влияние на скорость (или даже если это вообще происходит), это вне моей сферы знаний.

Одна вещь, которую я бы рассмотрела, - это фактические имена переменных. Это не имеет никакого значения для скомпилированного кода, но я предпочитаю более длинные имена переменных, а не сокращения, поэтому я бы выбрал kiloBytes/gigaBytes или что-то в этом роде. KB/GB слишком легко путать с константами, в зависимости от ваших стандартов кодирования.

Ответ 7

Я написал небольшой класс утилиты, который выполняет преобразования между единицами, 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;
    }
}

Ответ 8

Чтобы убедиться, что компилятор предварительно вычисляет делители:

decimal GB = KB / (1024 * 1024);

Обратите внимание, что вы фактически вычисляете GiB (gibibyte), а не GB (гигабайт). Если вы действительно хотите вычислить GB, это будет:

decimal GB = KB / (1000 * 1000);

Ответ 9

В теории это происходит быстрее (предварительно вычисляя константу для умножения вместо деления). Вероятно, он не используется достаточно часто, чтобы иметь значение, но на всякий случай.

double const KbToGbFactor = 1d / 1024 /1024;

double gb = kb * KbToGbFactor;

Ответ 10

Мне нужно было наоборот: конвертировать из стороннего компонента литерала в словах (например, "0 байт", "1,1 МБ" ) в общий размер в байтах. поэтому я использовал его так:

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

Ответ 11

Это небольшое улучшение хорошего ответа JLopez (пожалуйста, ГОЛОСОВАТЬ ЕГО, а не меня). Здесь вы можете выбрать или не указывать единицы измерения, а единица килограмма записывается в нижнем регистре "k" (верхний регистр для 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)}";
    }

Ответ 12

    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]);
    }

Ответ 13

#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;