Jak uzyskać czytelny dla człowieka rozmiar pliku w skrócie bajtów za pomocą .NET?


Odpowiedzi:


353

Nie jest to najskuteczniejszy sposób na zrobienie tego, ale łatwiej jest go przeczytać, jeśli nie znasz matematyki logów, i powinien być wystarczająco szybki dla większości scenariuszy.

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
Wierzę, że możesz użyć Math.Log, aby określić kolejność zamiast używać pętli while.
Francois Botha

12
Ponadto KB ma 1000 bajtów. 1024 bajty to KiB .
Constantin,

13
@Constantin dobrze, że zależy od systemu operacyjnego? Windows nadal liczy 1024 bajty jako 1 KB i 1 MB = 1024 KB, Osobiście chcę wyrzucić KiB przez okno i po prostu policzyć każdą rzecz przy użyciu 1024? ...
Peter

4
@Petoj to nie zależy od systemu operacyjnego, definicja jest zależna od systemu operacyjnego. Z Wikipedii: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
Wolę ten kod, ponieważ wydaje się on działać szybciej, ale nieco go zmodyfikowałem, aby uwzględnić inną liczbę miejsc dziesiętnych. Mniejsze liczby lepiej pokazują 2 miejsca po przecinku, np. 1,38 MB, podczas gdy większe liczby wymagają mniejszej liczby miejsc po przecinku, np. 246k lub 23,5KB:
Myke Black

321

za pomocą dziennika, aby rozwiązać problem ....

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

Również w języku c #, ale powinno to być szybkie przekształcenie. Również zaokrągliłem do 1 miejsca po przecinku dla czytelności.

Zasadniczo określ liczbę miejsc dziesiętnych w podstawie 1024, a następnie podziel przez 1024 ^ miejsca dziesiętne.

I kilka przykładów użycia i wyników:

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

Edycja: Zwrócono uwagę, że spóźniłem się na obliczenie matematyki, więc włączyłem ją. (Convert.ToInt32 używa zaokrąglania, a nie obcinania i dlatego Floor jest konieczny.) Dzięki za haczyk.

Edycja2: Było kilka komentarzy na temat rozmiarów ujemnych i 0 bajtów, więc zaktualizowałem, aby obsługiwać te 2 przypadki.


7
Chcę ostrzec, że chociaż ta odpowiedź jest rzeczywiście krótkim fragmentem kodu, nie jest najbardziej zoptymalizowana. Chciałbym, abyś spojrzał na metodę opublikowaną przez @humbads. Uruchomiłem mikrotestowanie, wysyłając 10 000 000 losowo wygenerowanych rozmiarów plików za pomocą obu metod, co powoduje, że jego metoda jest ~ 30% szybsza. Zrobiłem jednak pewne dalsze oczyszczenie jego metody (nieprzyzwoite zadania i casting). Ponadto przeprowadziłem test z ujemnym rozmiarem (podczas porównywania plików), podczas gdy metoda humbads bezbłędnie przetwarza tę metodę Loga, zgłasza wyjątek!
IvanL,

1
Tak, powinieneś dodać Math.Abs ​​dla ujemnych rozmiarów. Ponadto kod nie obsługuje przypadku, jeśli rozmiar wynosi dokładnie 0
dasheddot

Math.Abs, Math.Floor, Math.Log, Konwersja na liczbę całkowitą, Math.Round, Math.Pow, Math.Sign, Dodawanie, mnożenie, dzielenie? Czy to nie mnóstwo matematyki po prostu zrobiłoby ogromny skok na procesorze. Jest to prawdopodobnie wolniejsze niż kod @humbads
Jayson Ragasa,

Nie odpowiada double.MaxValue(miejsce = 102)
BrunoLM,

Działa świetnie! Aby naśladować sposób działania systemu Windows (przynajmniej w moim Windows 7 Ultimate), zamień Math.Round na Math.Ceiling. Dzięki jeszcze raz. Podoba mi się to rozwiązanie.
H_He

101

Testowana i znacznie zoptymalizowana wersja żądanej funkcji jest opublikowana tutaj:

C # Rozmiar pliku czytelny dla człowieka - funkcja zoptymalizowana

Kod źródłowy:

// 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! Prostsze i proste! Sprawia, że ​​procesor robi matematykę łatwo i szybciej!
Jayson Ragasa,

Do twojej wiadomości, double readable = (i < 0 ? -i : i);nigdzie nie używasz tej wartości, więc ją usuń. jeszcze jedno, obsada jest redaundat
Royi Namir

Usunąłem obsadę, dodałem komentarze i naprawiłem problem ze znakiem ujemnym.
humbads

Świetna odpowiedź. Dzięki, dlaczego nie po prostu użyć Math.Abs?
kspearrin

1
(i <0? -i: i) jest około 15% szybszy niż Math.Abs. W przypadku miliona połączeń Math.Abs ​​działa wolniej o 0,5 milisekundy na mojej maszynie - 3,2 ms w porównaniu z 3,7 ms.
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();
}

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


36
Mógłbym być noobem, ale użycie tak gigantycznej armaty jak pinvoke do zabicia tej kaczki jest dużym nadużyciem.
Bart

27
Czy tego używa Eksplorator? Jeśli tak, to niezwykle przydatne, aby pozwolić ludziom dopasować rozmiar pliku, który im pokazujesz, z tym, co pokazuje Eksplorator.
Andrew Backer,

8
I taki, który nie wymyśli na nowo koła
Matthew Lock

Czy 11 znaków nie jest dla tego stałym limitem i jest trochę za niskie? To znaczy, inne języki mogą używać więcej znaków dla akronimu rozmiaru bajtu lub innych stylów formatowania.
Ray

1
@Bart zajmuje trochę czasu, zanim nooby nauczyły się mądrości: „Powinniśmy zapomnieć o małej wydajności, powiedzmy w około 97% przypadków: przedwczesna optymalizacja jest źródłem wszelkiego zła” ubiquity.acm.org/article.cfm? id = 1513451
Matthew Lock

22

Jest jeszcze jeden sposób na skórowanie go, bez żadnych pętli i z obsługą ujemnego rozmiaru (ma sens w przypadku delt rozmiaru pliku):

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

A oto pakiet testowy:

[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

Checkout ByteSize bibliotekę. To System.TimeSpanbajty!

Obsługuje konwersję i formatowanie.

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

Wykonuje również reprezentację ciągów i parsowanie.

// 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
To twoja własna biblioteka, nie?
Larsenal

10
Bez wstydu w tak poręcznej bibliotece jak ta. :-)
Larsenal

13

Lubię używać następującej metody (obsługuje do terabajtów, co wystarcza w większości przypadków, ale można ją łatwo rozszerzyć):

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

Należy pamiętać, że jest to napisane dla C # 6.0 (2015), więc może wymagać niewielkiej edycji we wcześniejszych wersjach.


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

Dobra odpowiedź. Problem powinien występować, gdy rozmiar pliku jest zbyt mały, w takim przypadku / 1024 zwraca 0. Możesz użyć typu ułamkowego i wywołania Math.Ceilinglub czegoś takiego.
nawfal

10

Oto zwięzła odpowiedź, która automatycznie określa jednostkę.

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” oznacza bit, „B” oznacza bajt, a „KMGTPEZY” odpowiednio dla kilograma, mega, giga, tera, peta, exa, zetta i yotta

Można go rozszerzyć, aby uwzględnić 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
za każdy zastanawiać, dlaczego nie ma opo KMGTPE: francuskiego ( bytejest octetw języku francuskim). W przypadku każdego innego języka po prostu zamień onab
Max R.

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

Powinieneś sprawdzić: while (rozmiar> = 1024 && s <sufiksy. Długość).
TcKs,

nie ... 64-bitowa liczba całkowita ze znakiem nie może wykraczać poza ZB ... która reprezentuje liczby 2 ^ 70.
bobwienholt

7
Po co więc wkładać YB?
konfigurator

Najbardziej podoba mi się ta odpowiedź, ale wszyscy tutaj naprawdę wprowadzają naprawdę nieefektywne rozwiązania, powinieneś użyć zmiany „rozmiar = rozmiar >> 10” jest o wiele szybszy niż podział ... i myślę, że dobrze jest mieć dodatkowe greckie specyfikatory są dostępne, ponieważ w najbliższej przyszłości możliwa funkcja DLR nie będzie potrzebować „długiego rozmiaru ..” możesz być na 128-bitowym procesorze wektorowym lub czymś, co może pomieścić ZB i większe;)
RandomNickName42

4
Bitshifting był bardziej wydajny niż podział w czasach kodowania C na metalu. Czy wykonałeś test wydajności w .NET, aby sprawdzić, czy zmiana bitów naprawdę jest bardziej wydajna? Nie tak dawno temu spojrzałem na stan zamiany xor i stwierdziłem, że w rzeczywistości .NET jest wolniejszy niż przy użyciu zmiennej temp.
Pete,

7

Jeśli próbujesz dopasować rozmiar, jak pokazano w widoku szczegółów Eksploratora Windows, jest to odpowiedni kod:

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

Spowoduje to nie tylko dokładne dopasowanie Eksploratora, ale także zapewni przetłumaczone ciągi i różnice w wersjach systemu Windows (na przykład w Win10, K = 1000 w porównaniu do poprzednich wersji K = 1024).


Ten kod nie kompiluje się, musisz podać dll, z którego pochodzi funkcja. Prototyp całej funkcji brzmi następująco: [DllImport ("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern long StrFormatKBSize (long qdw, [MarshalAs (UnmanagedType.LPTStr)] StringBuilder pszBuf, int cchB ); Pozwól mi być pierwszym, który faworyzuje to rozwiązanie. Po co wymyślać koło, jeśli koło zostało już wynalezione? Jest to typowe podejście wszystkich programistów C #, ale niestety C # nie osiąga wszystkich celów, które osiąga C ++.
TarmoPikaro

I jeszcze jedna poprawka: Int64.MaxValue osiąga 9,223,372,036,854,775,807, co wymaga przydzielenia wielkości bufora 25+ - na wszelki wypadek zaokrągliłem ją do 32 (nie 11 jak w powyższym kodzie demonstracyjnym).
TarmoPikaro

Dzięki @TarmoPikaro. Kiedy skopiowałem z mojego działającego kodu, przegapiłem DllImport. Zwiększono także rozmiar bufora zgodnie z zaleceniami. Dobry chwyt!
Metalogiczny

imponujące podejście
tbhaxor

Pokazuje tylko jednostkę KB. Chodzi o to, aby pokazać największą jednostkę w zależności od wartości.
jstuardo

5

Mieszanka wszystkich rozwiązań :-)

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


3

Jak rozwiązanie @ NET3. Użyj shift zamiast podziału, aby przetestować zakres bytes, ponieważ podział wymaga więcej kosztów procesora.

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

Co powiesz na rekurencję:

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

Następnie nazywacie to:

return ReturnSize(size, string.Empty);

Dobrze, ale zjada procesor
kamalpreet

1

Moje 2 centy:

  • Prefiks kilobajta to kB (małe litery K)
  • Ponieważ funkcje te służą celom prezentacji, należy podać kulturę, na przykład: string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
  • W zależności od kontekstu kilobajt może mieć 1000 lub 1024 bajtów . To samo dotyczy MB, GB itp.

3
Kilobajt oznacza 1000 bajtów ( wolframalpha.com/input/?i=kilobyte ), nie zależy od kontekstu. To historycznie zależała od kontekstu, jak mówi wikipedia, i to było zmieniane de jure w 1998 roku i zmiana de facto rozpoczęła się około 2005 roku, kiedy terabajt dyski twarde przyniósł go do publicznej wiadomości. Termin 1024 bajtów to kibibajt. Kod przełączający je w oparciu o kulturę generuje nieprawidłowe informacje.
Superbest

1

Jeszcze jedno podejście, za które warto. Podobało mi się zoptymalizowane rozwiązanie @humbads, o którym mowa powyżej, więc skopiowałem zasadę, ale wdrożyłem ją nieco inaczej.

Podejrzewam, że jest dyskusyjne, czy powinna to być metoda rozszerzenia (ponieważ nie wszystkie długości są koniecznie rozmiarami bajtów), ale lubię je i gdzieś mogę znaleźć metodę, gdy będę jej potrzebować!

Jeśli chodzi o jednostki, wydaje mi się, że nigdy w życiu nie mówiłem „Kibibyte” lub „Mebibyte” i chociaż jestem sceptyczny wobec tak egzekwowanych, a nie ewoluowanych standardów, przypuszczam, że pozwoli to uniknąć zamieszania w perspektywie długoterminowej .

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

Używam metody Długie rozszerzenie poniżej, aby przekonwertować na ciąg rozmiaru czytelny dla człowieka. Ta metoda jest implementacją w języku C # rozwiązania Java dla tego samego pytania opublikowanego na stosie przepełnienia, tutaj .

/// <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";
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.