Как получить удобочитаемый размер файла в байтах, используя .NET?


Ответы:


353

Это не самый эффективный способ сделать это, но его легче читать, если вы не знакомы с математикой журнала, и он должен быть достаточно быстрым для большинства сценариев.

string[] sizes = { "B", "KB", "MB", "GB", "TB" };
double len = new FileInfo(filename).Length;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1) {
    order++;
    len = len/1024;
}

// Adjust the format string to your preferences. For example "{0:0.#}{1}" would
// show a single decimal place, and no space.
string result = String.Format("{0:0.##} {1}", len, sizes[order]);

12
Я полагаю, что вы могли бы использовать Math.Log для определения порядка вместо использования цикла while.
— Франсуа Бота

12
Кроме того, КБ составляет 1000 байтов. 1024 байта - это КиБ .
— Константин

13
@ Константин ну что зависит от ОС? Windows по-прежнему считает 1024 байта как 1 КБ и 1 МБ = 1024 КБ. Лично я хочу выбросить KiB из окна и просто считать каждую вещь, используя 1024? ...
— Питер

4
@Petoj это не зависит от ОС, определение не зависит от ОС. Материал из Википедии:The unit was established by the International Electrotechnical Commission (IEC) in 1998 and has been accepted for use by all major standards organizations
— ANeves

3
Я предпочитаю этот код, так как он работает быстрее, но я немного изменил его, чтобы учесть различное количество десятичных знаков. Меньшие числа лучше отображать с двумя десятичными разрядами, например, 1,38 МБ, тогда как для больших чисел требуется меньше десятичных разрядов, например, 246 КБ или 23,5 КБ:
— Myke Black

321

используя журнал для решения проблемы ....

static String BytesToString(long byteCount)
{
    string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; //Longs run out around EB
    if (byteCount == 0)
        return "0" + suf[0];
    long bytes = Math.Abs(byteCount);
    int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
    double num = Math.Round(bytes / Math.Pow(1024, place), 1);
    return (Math.Sign(byteCount) * num).ToString() + suf[place];
}

Также в C #, но должно быть легко конвертировать. Также я округлил до 1 десятичного знака для удобства чтения.

В основном определите количество десятичных знаков в базе 1024, а затем разделите на 1024 ^ десятичных знаков.

И некоторые примеры использования и вывода:

Console.WriteLine(BytesToString(9223372036854775807));  //Results in 8EB
Console.WriteLine(BytesToString(0));                    //Results in 0B
Console.WriteLine(BytesToString(1024));                 //Results in 1KB
Console.WriteLine(BytesToString(2000000));              //Results in 1.9MB
Console.WriteLine(BytesToString(-9023372036854775807)); //Results in -7.8EB

Изменить: было указано, что я пропустил math.floor, поэтому я включил его. (Convert.ToInt32 использует округление, а не усечение, и поэтому необходим Floor.) Спасибо за улов.

Edit2: было несколько комментариев об отрицательных размерах и 0 байтных размерах, поэтому я обновил, чтобы обработать эти 2 случая.


7
Я хочу предупредить, что хотя этот ответ действительно является небольшим фрагментом кода, он не самый оптимизированный. Я бы хотел, чтобы вы взглянули на метод, опубликованный @humbads. Я провел микротестирование, отправив 10 000 000 случайно сгенерированных файловых форматов обоими методами, и это приводит к выводу, что его метод работает на ~ 30% быстрее. Однако я провел дальнейшую очистку его метода (ненужные задания и кастинг). Кроме того, я запустил тест с отрицательным размером (когда вы сравниваете файлы), в то время как метод хумбада безошибочно обрабатывает этот метод Log, и он выдаст исключение!
— IvanL

1
Да, вы должны добавить Math.Abs ​​для отрицательных размеров. Кроме того, код не обрабатывает случай, если размер точно равен 0.
— dasheddot

Math.Abs, Math.Floor, Math.Log, Преобразование в целое число, Math.Round, Math.Pow, Math.Sign, Добавление, Умножение, Деление? Разве эта тонна математики не сделала огромный скачок на процессоре. Это, вероятно, медленнее, чем код @humbads
— Джейсон Рагаса

Сбой double.MaxValue(место = 102)
— BrunoLM

Прекрасно работает! Чтобы имитировать работу окон (по крайней мере на моем Windows 7 Ultimate), замените Math.Round на Math.Ceiling. Еще раз спасибо. Мне нравится это решение.
— H_He

101

Тестовая и значительно оптимизированная версия запрашиваемой функции размещена здесь:

C # Удобочитаемый размер файла - оптимизированная функция

Исходный код:

// Returns the human-readable file size for an arbitrary, 64-bit file size 
// The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
public string GetBytesReadable(long i)
{
    // Get absolute value
    long absolute_i = (i < 0 ? -i : i);
    // Determine the suffix and readable value
    string suffix;
    double readable;
    if (absolute_i >= 0x1000000000000000) // Exabyte
    {
        suffix = "EB";
        readable = (i >> 50);
    }
    else if (absolute_i >= 0x4000000000000) // Petabyte
    {
        suffix = "PB";
        readable = (i >> 40);
    }
    else if (absolute_i >= 0x10000000000) // Terabyte
    {
        suffix = "TB";
        readable = (i >> 30);
    }
    else if (absolute_i >= 0x40000000) // Gigabyte
    {
        suffix = "GB";
        readable = (i >> 20);
    }
    else if (absolute_i >= 0x100000) // Megabyte
    {
        suffix = "MB";
        readable = (i >> 10);
    }
    else if (absolute_i >= 0x400) // Kilobyte
    {
        suffix = "KB";
        readable = i;
    }
    else
    {
        return i.ToString("0 B"); // Byte
    }
    // Divide by 1024 to get fractional value
    readable = (readable / 1024);
    // Return formatted number with suffix
    return readable.ToString("0.### ") + suffix;
}

1
+1! Проще и проще! Заставляет процессор выполнять математику легко и быстро!
— Джейсон Рагаса

К вашему сведению, вы нигде не используете это значение, double readable = (i < 0 ? -i : i);поэтому удалите его. еще один актерский состав - редунат
— Ройи Намир,

Я удалил актерский состав, добавил комментарии и исправил проблему со знаком минус.
— хамбадс

Отличный ответ. Спасибо, почему бы просто не использовать Math.Abs?
— kspearrin

1
(i <0? -i: i) примерно на 15% быстрее, чем Math.Abs. Для одного миллиона вызовов Math.Abs ​​на моей машине медленнее на 0,5 миллисекунды - 3,2 мс против 3,7 мс.
— Humbads

72
[DllImport ( "Shlwapi.dll", CharSet = CharSet.Auto )]
public static extern long StrFormatByteSize ( 
        long fileSize
        , [MarshalAs ( UnmanagedType.LPTStr )] StringBuilder buffer
        , int bufferSize );


/// <summary>
/// Converts a numeric value into a string that represents the number expressed as a size value in bytes, kilobytes, megabytes, or gigabytes, depending on the size.
/// </summary>
/// <param name="filelength">The numeric value to be converted.</param>
/// <returns>the converted string</returns>
public static string StrFormatByteSize (long filesize) {
     StringBuilder sb = new StringBuilder( 11 );
     StrFormatByteSize( filesize, sb, sb.Capacity );
     return sb.ToString();
}

От: http://www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html


36
Я мог бы быть нубом, но использование такой гигантской пушки, как pinvoke для убийства этой утки, является большим злоупотреблением.
— Барт

27
Это то, что использует проводник? Если это так, то он очень полезен для того, чтобы позволить людям соответствовать размеру файла, который вы им показываете, и тому, что показывает проводник.
— Эндрю Бакер

8
И тот, который не изобретает велосипед
— Мэтью Локк

Разве 11 символов не являются постоянным лимитом и немного низкими для этого? Я имею в виду, что другие языки могут использовать больше символов для сокращения размера в байтах или других стилей форматирования.
— Рэй

1
@ Но новичкам нужно некоторое время, чтобы научиться мудрости в этом: «Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла» ubiquity.acm.org/article.cfm? id = 1513451
— Мэтью Локк

22

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

public static class Format
{
    static string[] sizeSuffixes = {
        "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

    public static string ByteSize(long size)
    {
        Debug.Assert(sizeSuffixes.Length > 0);

        const string formatTemplate = "{0}{1:0.#} {2}";

        if (size == 0)
        {
            return string.Format(formatTemplate, null, 0, sizeSuffixes[0]);
        }

        var absSize = Math.Abs((double)size);
        var fpPower = Math.Log(absSize, 1000);
        var intPower = (int)fpPower;
        var iUnit = intPower >= sizeSuffixes.Length
            ? sizeSuffixes.Length - 1
            : intPower;
        var normSize = absSize / Math.Pow(1000, iUnit);

        return string.Format(
            formatTemplate,
            size < 0 ? "-" : null, normSize, sizeSuffixes[iUnit]);
    }
}

А вот и тестовый набор:

[TestFixture] public class ByteSize
{
    [TestCase(0, Result="0 B")]
    [TestCase(1, Result = "1 B")]
    [TestCase(1000, Result = "1 KB")]
    [TestCase(1500000, Result = "1.5 MB")]
    [TestCase(-1000, Result = "-1 KB")]
    [TestCase(int.MaxValue, Result = "2.1 GB")]
    [TestCase(int.MinValue, Result = "-2.1 GB")]
    [TestCase(long.MaxValue, Result = "9.2 EB")]
    [TestCase(long.MinValue, Result = "-9.2 EB")]
    public string Format_byte_size(long size)
    {
        return Format.ByteSize(size);
    }
}

19

Оформить заказ на библиотеку ByteSize . Это System.TimeSpanдля байтов!

Он обрабатывает преобразование и форматирование для вас.

var maxFileSize = ByteSize.FromKiloBytes(10);
maxFileSize.Bytes;
maxFileSize.MegaBytes;
maxFileSize.GigaBytes;

Это также делает строковое представление и анализ.

// ToString
ByteSize.FromKiloBytes(1024).ToString(); // 1 MB
ByteSize.FromGigabytes(.5).ToString();   // 512 MB
ByteSize.FromGigabytes(1024).ToString(); // 1 TB

// Parsing
ByteSize.Parse("5b");
ByteSize.Parse("1.55B");

5
Это твоя собственная библиотека, нет?
— Ларсенал

10
Нет ничего постыдного в такой удобной библиотеке. :-)
— Ларсенал

13

Мне нравится использовать следующий метод (он поддерживает до терабайтов, что достаточно для большинства случаев, но его легко расширить):

private string GetSizeString(long length)
{
    long B = 0, KB = 1024, MB = KB * 1024, GB = MB * 1024, TB = GB * 1024;
    double size = length;
    string suffix = nameof(B);

    if (length >= TB) {
        size = Math.Round((double)length / TB, 2);
        suffix = nameof(TB);
    }
    else if (length >= GB) {
        size = Math.Round((double)length / GB, 2);
        suffix = nameof(GB);
    }
    else if (length >= MB) {
        size = Math.Round((double)length / MB, 2);
        suffix = nameof(MB);
    }
    else if (length >= KB) {
        size = Math.Round((double)length / KB, 2);
        suffix = nameof(KB);
    }

    return $"{size} {suffix}";
}

Помните, что это написано для C # 6.0 (2015), поэтому для более ранних версий может потребоваться небольшое редактирование.


11
int size = new FileInfo( filePath ).Length / 1024;
string humanKBSize = string.Format( "{0} KB", size );
string humanMBSize = string.Format( "{0} MB", size / 1024 );
string humanGBSize = string.Format( "{0} GB", size / 1024 / 1024 );

Хороший ответ. Должна быть проблема, когда размер файла слишком мал, и в этом случае / 1024 возвращает 0. Вы можете использовать дробный тип и вызов Math.Ceilingили что-то еще.
— Nawfal

10

Вот краткий ответ, который определяет единицу автоматически.

public static string ToBytesCount(this long bytes)
{
    int unit = 1024;
    string unitStr = "b";
    if (bytes < unit) return string.Format("{0} {1}", bytes, unitStr);
    else unitStr = unitStr.ToUpper();
    int exp = (int)(Math.Log(bytes) / Math.Log(unit));
    return string.Format("{0:##.##} {1}{2}", bytes / Math.Pow(unit, exp), "KMGTPEZY"[exp - 1], unitStr);
}

«b» для бита, «B» для байта и «KMGTPEZY» соответственно для кило, мега, гига, тера, пета, exa, zetta и yotta

Можно расширить его, чтобы принять во внимание ISO / IEC80000 :

public static string ToBytesCount(this long bytes, bool isISO = true)
{
    int unit = 1024;
    string unitStr = "b";
    if (!isISO) unit = 1000;
    if (bytes < unit) return string.Format("{0} {1}", bytes, unitStr);
    else unitStr = unitStr.ToUpper();
    if (isISO) unitStr = "i" + unitStr;
    int exp = (int)(Math.Log(bytes) / Math.Log(unit));
    return string.Format("{0:##.##} {1}{2}", bytes / Math.Pow(unit, exp), "KMGTPEZY"[exp - 1], unitStr);
}

1
для всех интересно , почему есть oпосле того, как KMGTPE: Его французский ( byteэто octetна французском языке). Для любого другого языка просто заменить oсb
— Макс Р.

7
string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
int s = 0;
long size = fileInfo.Length;

while (size >= 1024)
{
    s++;
    size /= 1024;
}

string humanReadable = String.Format("{0} {1}", size, suffixes[s]);

Вы должны проверить: while (size> = 1024 && s <suffixes.Length).
— TcKs

Нет ... 64-разрядное целое число со знаком не может выходить за пределы ZB ..., которое представляет числа 2 ^ 70.
— bobwienholt

7
Так зачем ставить в YB?
— Конфигуратор

Мне самому этот ответ нравится больше всего, но все здесь действительно вкладывают действительно неэффективные решения, вы должны использовать "size = size >> 10", смещение намного быстрее, чем деление ... и я думаю, что хорошо иметь здесь есть дополнительный греческий спецификатор, потому что в ближайшем будущем положительной функции DLR не потребуется «длинный размер». Вы можете использовать 128-битный векторный процессор или что-то, что может содержать ZB и больше;)
— RandomNickName42

4
Bitshifting был более эффективным, чем деление во времена кодирования C на металле. Вы провели тестирование на .NET, чтобы увидеть, действительно ли бит-смещение более эффективно? Не так давно я посмотрел на состояние xor-swap и обнаружил, что он на самом деле медленнее в .NET по сравнению с использованием временной переменной.
— Пит

7

Если вы пытаетесь соответствовать размеру, как показано в подробном представлении Windows Explorer, вам нужен следующий код:

[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern long StrFormatKBSize(
    long qdw,
    [MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszBuf,
    int cchBuf);

public static string BytesToString(long byteCount)
{
    var sb = new StringBuilder(32);
    StrFormatKBSize(byteCount, sb, sb.Capacity);
    return sb.ToString();
}

Это будет не только точно соответствовать Explorer, но также предоставит переведенные для вас строки и совпадет с различиями в версиях Windows (например, в Win10, K = 1000 против предыдущих версий K = 1024).


Этот код не компилируется, вам нужно указать dll, из которой пришла функция. Таким образом, весь прототип функции звучит так: [DllImport ("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)] общедоступный статический extern long StrFormatKBSize (long qdw, [MarshalAs (UnmanagedType.LPTStr)] StringBuilder int cszBuf, ); Позвольте мне быть первым, кто поддержит это решение. Зачем изобретать велосипед, если колесо уже изобретено? Это типичный подход всех программистов на C #, но, к сожалению, C # не достигает всех целей, которых достигает C ++.
— TarmoPikaro

И еще одно исправление: Int64.MaxValue достигает 9,223,372,036,854,775,807, что требует выделения размера буфера 25+ - на всякий случай я округлил его до 32 (а не 11, как в демонстрационном коде выше).
— TarmoPikaro

Спасибо @TarmoPikaro. Когда я скопировал из моего рабочего кода, я пропустил DllImport. Также увеличен размер буфера по вашей рекомендации. Хороший улов!
— Metalogic

Впечатляющий подход
— tbhaxor

Это показывает только единицу КБ. Идея состоит в том, чтобы показать самую большую единицу в зависимости от стоимости.
— jstuardo

5

Смесь всех решений :-)

    /// <summary>
    /// Converts a numeric value into a string that represents the number expressed as a size value in bytes,
    /// kilobytes, megabytes, or gigabytes, depending on the size.
    /// </summary>
    /// <param name="fileSize">The numeric value to be converted.</param>
    /// <returns>The converted string.</returns>
    public static string FormatByteSize(double fileSize)
    {
        FileSizeUnit unit = FileSizeUnit.B;
        while (fileSize >= 1024 && unit < FileSizeUnit.YB)
        {
            fileSize = fileSize / 1024;
            unit++;
        }
        return string.Format("{0:0.##} {1}", fileSize, unit);
    }

    /// <summary>
    /// Converts a numeric value into a string that represents the number expressed as a size value in bytes,
    /// kilobytes, megabytes, or gigabytes, depending on the size.
    /// </summary>
    /// <param name="fileInfo"></param>
    /// <returns>The converted string.</returns>
    public static string FormatByteSize(FileInfo fileInfo)
    {
        return FormatByteSize(fileInfo.Length);
    }
}

public enum FileSizeUnit : byte
{
    B,
    KB,
    MB,
    GB,
    TB,
    PB,
    EB,
    ZB,
    YB
}

4

Есть один проект с открытым исходным кодом, который может сделать это и многое другое.

7.Bits().ToString();         // 7 b
8.Bits().ToString();         // 1 B
(.5).Kilobytes().Humanize();   // 512 B
(1000).Kilobytes().ToString(); // 1000 KB
(1024).Kilobytes().Humanize(); // 1 MB
(.5).Gigabytes().Humanize();   // 512 MB
(1024).Gigabytes().ToString(); // 1 TB

http://humanizr.net/#bytesize

https://github.com/MehdiK/Humanizer


3

Как и решение @ NET3. Используйте сдвиг вместо деления для проверки диапазона bytes, потому что деление требует больше ресурсов процессора.

private static readonly string[] UNITS = new string[] { "B", "KB", "MB", "GB", "TB", "PB", "EB" };

public static string FormatSize(ulong bytes)
{
    int c = 0;
    for (c = 0; c < UNITS.Length; c++)
    {
        ulong m = (ulong)1 << ((c + 1) * 10);
        if (bytes < m)
            break;
    }

    double n = bytes / (double)((ulong)1 << (c * 10));
    return string.Format("{0:0.##} {1}", n, UNITS[c]);
}

2

Я полагаю, вы ищете "1,4 МБ" вместо "1468006 байт"?

Я не думаю, что есть встроенный способ сделать это в .NET. Вам нужно просто выяснить, какой блок подходит, и отформатировать его.

Изменить: Вот пример кода, чтобы сделать это:

http://www.codeproject.com/KB/cpp/formatsize.aspx


2

Как насчет рекурсии:

private static string ReturnSize(double size, string sizeLabel)
{
  if (size > 1024)
  {
    if (sizeLabel.Length == 0)
      return ReturnSize(size / 1024, "KB");
    else if (sizeLabel == "KB")
      return ReturnSize(size / 1024, "MB");
    else if (sizeLabel == "MB")
      return ReturnSize(size / 1024, "GB");
    else if (sizeLabel == "GB")
      return ReturnSize(size / 1024, "TB");
    else
      return ReturnSize(size / 1024, "PB");
  }
  else
  {
    if (sizeLabel.Length > 0)
      return string.Concat(size.ToString("0.00"), sizeLabel);
    else
      return string.Concat(size.ToString("0.00"), "Bytes");
  }
}

Тогда вы называете это:

return ReturnSize(size, string.Empty);

Хорошо, но ест процессор
— kamalpreet

1

Мои 2 цента:

  • Префикс для килобайта - кБ (строчная буква K)
  • Поскольку эти функции предназначены для презентаций, необходимо предоставить культуру, например: string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
  • В зависимости от контекста килобайт может быть либо 1000, либо 1024 байта . То же самое касается МБ, ГБ и т. Д.

3
Килобайт означает 1000 байтов ( wolframalpha.com/input/?i=kilobyte ), это не зависит от контекста. Как говорит Википедия, он исторически зависел от контекста, и де-юре он был изменен в 1998 году, а изменения де-факто начались примерно в 2005 году, когда терабайтные жесткие диски привлекли его внимание общественности. Термин для 1024 байтов - это кибибайт. Код, который переключает их в зависимости от культуры, производит неверную информацию.
— Супербест

1

Еще один подход, для чего это стоит. Мне понравилось оптимизированное решение @humbads, упомянутое выше, поэтому я скопировал этот принцип, но я реализовал его немного по-другому.

Я предполагаю, что это спорный вопрос о том, должен ли это быть метод расширения (поскольку не все длинные значения обязательно имеют размер в байтах), но они мне нравятся, и где-то я могу найти метод, когда он мне понадобится в следующий раз!

Что касается юнитов, я не думаю, что когда-либо говорил «Kibibyte» или «Mebibyte» в своей жизни, и, хотя я скептически отношусь к таким неукоснительным, а не к развитым стандартам, я полагаю, что в долгосрочной перспективе это позволит избежать путаницы ,

public static class LongExtensions
{
    private static readonly long[] numberOfBytesInUnit;
    private static readonly Func<long, string>[] bytesToUnitConverters;

    static LongExtensions()
    {
        numberOfBytesInUnit = new long[6]    
        {
            1L << 10,    // Bytes in a Kibibyte
            1L << 20,    // Bytes in a Mebibyte
            1L << 30,    // Bytes in a Gibibyte
            1L << 40,    // Bytes in a Tebibyte
            1L << 50,    // Bytes in a Pebibyte
            1L << 60     // Bytes in a Exbibyte
        };

        // Shift the long (integer) down to 1024 times its number of units, convert to a double (real number), 
        // then divide to get the final number of units (units will be in the range 1 to 1023.999)
        Func<long, int, string> FormatAsProportionOfUnit = (bytes, shift) => (((double)(bytes >> shift)) / 1024).ToString("0.###");

        bytesToUnitConverters = new Func<long,string>[7]
        {
            bytes => bytes.ToString() + " B",
            bytes => FormatAsProportionOfUnit(bytes, 0) + " KiB",
            bytes => FormatAsProportionOfUnit(bytes, 10) + " MiB",
            bytes => FormatAsProportionOfUnit(bytes, 20) + " GiB",
            bytes => FormatAsProportionOfUnit(bytes, 30) + " TiB",
            bytes => FormatAsProportionOfUnit(bytes, 40) + " PiB",
            bytes => FormatAsProportionOfUnit(bytes, 50) + " EiB",
        };
    }

    public static string ToReadableByteSizeString(this long bytes)
    {
        if (bytes < 0)
            return "-" + Math.Abs(bytes).ToReadableByteSizeString();

        int counter = 0;
        while (counter < numberOfBytesInUnit.Length)
        {
            if (bytes < numberOfBytesInUnit[counter])
                return bytesToUnitConverters[counter](bytes);
            counter++;
        }
        return bytesToUnitConverters[counter](bytes);
    }
}

0

Я использую метод длинного расширения, приведенный ниже, чтобы преобразовать его в удобочитаемую строку размера. Этот метод является реализацией C # решения Java этого же вопроса, опубликованного в Stack Overflow, здесь .

/// <summary>
/// Convert a byte count into a human readable size string.
/// </summary>
/// <param name="bytes">The byte count.</param>
/// <param name="si">Whether or not to use SI units.</param>
/// <returns>A human readable size string.</returns>
public static string ToHumanReadableByteCount(
    this long bytes
    , bool si
)
{
    var unit = si
        ? 1000
        : 1024;

    if (bytes < unit)
    {
        return $"{bytes} B";
    }

    var exp = (int) (Math.Log(bytes) / Math.Log(unit));

    return $"{bytes / Math.Pow(unit, exp):F2} " +
           $"{(si ? "kMGTPE" : "KMGTPE")[exp - 1] + (si ? string.Empty : "i")}B";
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.