Как получить удобочитаемый размер файла в байтах, используя .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.