Comment obtenir une taille de fichier lisible par l'homme en abréviation d'octets à l'aide de .NET?

Réponses:

353

Ce n'est pas le moyen le plus efficace de le faire, mais il est plus facile à lire si vous n'êtes pas familier avec les mathématiques des journaux et devrait être assez rapide pour la plupart des scénarios.

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]);
David Thibault
la source
12
Je pense que vous pouvez utiliser Math.Log pour déterminer l'ordre au lieu d'utiliser une boucle while.
Francois Botha
12
En outre, KB est de 1000 octets. 1024 octets est KiB .
Constantin
13
@Constantin ça dépend bien de l'OS? Windows compte toujours 1024 octets comme 1 Ko et 1 Mo = 1024 Ko. Personnellement, je veux jeter le KiB par la fenêtre et compter tout en utilisant 1024? ...
Peter
4
@Petoj cela ne dépend pas du système d'exploitation, la définition est indépendante du système d'exploitation. De Wikipedia: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
Je préfère ce code car il semble fonctionner plus rapidement mais je l'ai légèrement modifié pour permettre différents nombres de décimales. Les petits nombres affichent mieux 2 décimales, par exemple 1,38 Mo, tandis que les grands nombres nécessitent moins de décimales, par exemple 246 Ko ou 23,5 Ko:
Myke Black
321

utiliser Log pour résoudre le problème ....

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

Également en c #, mais devrait être un composant logiciel enfichable à convertir. J'ai également arrondi à 1 décimale pour plus de lisibilité.

Fondamentalement, déterminez le nombre de décimales dans Base 1024, puis divisez par 1024 ^ décimales.

Et quelques exemples d'utilisation et de sortie:

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

Edit: On m'a fait remarquer que j'avais raté un plancher mathématique, alors je l'ai incorporé. (Convert.ToInt32 utilise l'arrondi, pas la troncature et c'est pourquoi Floor est nécessaire.) Merci pour la capture.

Edit2: Il y avait quelques commentaires sur les tailles négatives et les tailles 0 octet, j'ai donc mis à jour pour gérer ces 2 cas.

deepee1
la source
7
Je tiens à avertir que bien que cette réponse soit en effet un court morceau de code, elle n'est pas la plus optimisée. J'aimerais que vous jetiez un œil à la méthode publiée par @humbads. J'ai effectué des microtests en envoyant 10 000 000 de tailles de fichiers générées aléatoirement via les deux méthodes, ce qui fait apparaître que sa méthode est ~ 30% plus rapide. J'ai cependant fait un peu de nettoyage supplémentaire de sa méthode (missions et casting non nécessaires). De plus, j'ai effectué un test avec une taille négative (lorsque vous comparez des fichiers) tandis que la méthode des humbads traite parfaitement cette méthode Log qui lèvera une exception!
IvanL
1
Oui, vous devez ajouter Math.Abs ​​pour les tailles négatives. De plus, le code ne gère pas le cas si la taille est exactement 0.
dasheddot
Math.Abs, Math.Floor, Math.Log, Conversion en entier, Math.Round, Math.Pow, Math.Sign, Ajout, Multiplication, Division? N'était-ce pas cette tonne de maths qui faisait juste un énorme pic sur le processeur. C'est probablement plus lent que le code @humbads
Jayson Ragasa
Échoue pour double.MaxValue(place = 102)
BrunoLM
Fonctionne très bien! Pour imiter le fonctionnement de Windows (au moins sur mon Windows 7 Ultimate), remplacez Math.Round par Math.Ceiling. Merci encore. J'aime cette solution.
H_He
101

Une version testée et considérablement optimisée de la fonction demandée est publiée ici:

Taille de fichier lisible par l'homme C # - Fonction optimisée

Code source:

// 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;
}
humbads
la source
1
+1! Plus simple et direct! Permet au processeur de faire le calcul facilement et plus rapidement!
Jayson Ragasa
Pour info, vous n'utilisez la valeur double readable = (i < 0 ? -i : i);nulle part, donc supprimez-la. une dernière chose, le casting est redaundat
Royi Namir
J'ai supprimé la distribution, ajouté des commentaires et résolu un problème avec le signe négatif.
humbads
Très bonne réponse. Merci, pourquoi ne pas simplement utiliser Math.Abs?
kspearrin
1
(i <0? -i: i) est environ 15% plus rapide que Math.Abs. Pour un million d'appels, Math.Abs ​​est 0,5 millisecondes plus lent sur ma machine - 3,2 ms contre 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();
}

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

Bob
la source
36
Je suis peut-être un noob, mais utiliser un canon aussi gigantesque que pinvoke pour tuer ce canard est une mauvaise utilisation.
Bart
27
Est-ce ce que l'explorateur utilise? Si oui, alors magnifiquement utile pour permettre aux gens de faire correspondre la taille du fichier que vous leur montrez avec ce que l'explorateur montre.
Andrew Backer
8
Et celui qui ne réinvente pas la roue
Matthew Lock
N'est-ce pas 11 caractères une limite constante et un peu faible pour cela? Je veux dire, d'autres langues peuvent utiliser plus de caractères pour l'acronyme de taille d'octet ou d'autres styles de formatage.
Ray
1
@Bart il faut un certain temps aux noobs pour apprendre la sagesse en ceci: "Nous devons oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tout mal" ubiquity.acm.org/article.cfm? id = 1513451
Matthew Lock
22

Une autre façon de l'habiller, sans aucune sorte de boucles et avec un support de taille négative (est logique pour des choses comme les deltas de taille de fichier):

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

Et voici la suite de tests:

[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);
    }
}
Constantin
la source
19

La caisse ByteSize bibliothèque. C'est pour les System.TimeSpanoctets!

Il gère la conversion et le formatage pour vous.

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

Il effectue également la représentation et l'analyse des chaînes.

// 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");
Omar
la source
5
C'est votre propre bibliothèque, non?
Larsenal
10
Pas de honte dans une bibliothèque pratique comme celle-ci. :-)
Larsenal
13

J'aime utiliser la méthode suivante (elle prend en charge jusqu'à téraoctets, ce qui est suffisant dans la plupart des cas, mais elle peut facilement être étendue):

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

Veuillez garder à l'esprit que cela est écrit pour C # 6.0 (2015), donc il pourrait avoir besoin d'un peu de modification pour les versions antérieures.

marque
la source
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 );
TcKs
la source
Bonne réponse. Il devrait y avoir un problème lorsque la taille du fichier est trop petite, auquel cas / 1024 renvoie 0. Vous pouvez utiliser un type fractionnaire et appeler Math.Ceilingou quelque chose.
nawfal
10

Voici une réponse concise qui détermine automatiquement l'unité.

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" est pour le bit, "B" est pour l'octet et "KMGTPEZY" sont respectivement pour le kilo, le méga, le giga, le tera, le peta, l'exa, le zetta et le yotta

On peut l'étendre pour prendre en compte 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);
}
DKH
la source
1
pour tout le monde demande pourquoi il y a un oaprès KMGTPE: Son français ( byteest octeten français). Pour toute autre langue, remplacez simplement le oparb
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]);
bobwienholt
la source
Vous devez vérifier: while (size> = 1024 && s <suffixes.Length).
TcKs
non ... un entier signé 64 bits ne peut pas dépasser le ZB ... qui représente les nombres 2 ^ 70.
bobwienholt
7
Alors pourquoi mettre YB?
configurateur
J'aime mieux cette réponse moi-même, mais tout le monde ici propose des solutions vraiment inefficaces, vous devriez utiliser "size = size >> 10", le décalage est donc beaucoup plus rapide que la division ... et je pense que c'est bien d'avoir le un spécificateur grec supplémentaire est là, car dans un avenir proche, une fonction DLR posiable n'aurait pas besoin de la "taille longue .." vous pourriez être sur un processeur vectoriel 128 bits ou quelque chose qui peut contenir ZB et plus grand;)
RandomNickName42
4
Le bitshifting était plus efficace que la division à l'époque du codage C sur le métal. Avez-vous fait un test de perf dans .NET pour voir si le décalage est vraiment plus efficace? Il n'y a pas si longtemps, j'ai regardé l'état du xor-swap et j'ai trouvé qu'il était en fait plus lent dans .NET qu'avec une variable temporaire.
Pete
7

Si vous essayez de faire correspondre la taille comme indiqué dans la vue détaillée de l'Explorateur Windows, voici le code que vous souhaitez:

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

Cela correspondra non seulement à l'Explorateur, mais fournira également les chaînes traduites pour vous et correspondra aux différences dans les versions de Windows (par exemple dans Win10, K = 1000 par rapport aux versions précédentes K = 1024).

Metalogic
la source
Ce code ne se compile pas, vous devez spécifier la DLL d'où provient la fonction. Ainsi, le prototype de la fonction entière ressemble à ceci: [DllImport ("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static external long StrFormatKBSize (long qdw, [MarshalAs (UnmanagedType.LPTStr)] StringBuilder pszBuf, int cchBufuf ); Permettez-moi d'être le premier à favoriser cette solution. Pourquoi réinventer la roue si la roue a déjà été inventée? C'est l'approche typique de tous les programmeurs C #, mais malheureusement C # n'atteint pas toutes les cibles atteintes par C ++.
TarmoPikaro
Et un autre bugfix: Int64.MaxValue atteint 9.223.372.036.854.775.807, ce qui nécessite d'allouer une taille de tampon de 25+ - je l'ai arrondi à 32 au cas où (pas 11 comme dans le code de démonstration ci-dessus).
TarmoPikaro
Merci @TarmoPikaro. Lorsque j'ai copié à partir de mon code de travail, j'ai raté le DllImport. Également augmenté la taille du tampon selon votre recommandation. Bonne prise!
Metalogic
approche impressionnante
tbhaxor
Cela montre uniquement l'unité KB. L'idée est de montrer la plus grande unité en fonction de la valeur.
jstuardo
5

Mélange de toutes les solutions :-)

    /// <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
}
NET3
la source
4

Il existe un projet open source qui peut le faire et bien plus encore.

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

Jernej Novak
la source
3

Comme la solution de @ NET3. Utilisez shift au lieu de division pour tester la plage de bytes, car la division prend plus de coûts CPU.

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]);
}
user1448446
la source
2

Je suppose que vous recherchez "1,4 Mo" au lieu de "1468006 octets"?

Je ne pense pas qu'il existe un moyen intégré de le faire dans .NET. Vous devrez simplement déterminer quelle unité est appropriée et la formater.

Edit: Voici quelques exemples de code pour faire exactement cela:

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

Peter Crabtree
la source
2

Que diriez-vous d'une récursivité:

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

Ensuite, vous l'appelez:

return ReturnSize(size, string.Empty);
RooiWillie
la source
Bon mais il mange CPU
kamalpreet
1

Mes 2 cents:

  • Le préfixe pour le kilo-octet est kB (K minuscule)
  • Étant donné que ces fonctions sont à des fins de présentation, il convient de fournir une culture, par exemple: string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
  • Selon le contexte, un kilo-octet peut être de 1 000 ou 1 024 octets . Il en va de même pour les Mo, les Go, etc.
Berend
la source
3
Un kilo-octet signifie 1000 octets ( wolframalpha.com/input/?i=kilobyte ), cela ne dépend pas du contexte. Il dépendait historiquement du contexte, comme le dit Wikipédia, et il a été de jure changé en 1998 et un changement de facto a commencé vers 2005 lorsque les disques durs de téraoctets l'ont porté à l'attention du public. Le terme pour 1024 octets est kibioctet. Le code qui les change en fonction de la culture produit des informations incorrectes.
Superbe le
1

Une approche de plus, pour ce que ça vaut. J'ai aimé la solution optimisée @humbads référencée ci-dessus, j'ai donc copié le principe, mais je l'ai implémenté un peu différemment.

Je suppose qu'il est discutable de savoir si ce devrait être une méthode d'extension (car tous les longs ne sont pas nécessairement des tailles d'octets), mais je les aime, et c'est quelque part où je peux trouver la méthode lorsque j'en aurai besoin!

En ce qui concerne les unités, je ne pense pas avoir jamais dit «Kibibyte» ou «Mebibyte» dans ma vie, et bien que je sceptique quant à ces normes appliquées plutôt qu'évolues, je suppose que cela évitera la confusion à long terme .

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);
    }
}
Giles
la source
0

J'utilise la méthode d'extension longue ci-dessous pour convertir en une chaîne de taille lisible par l'homme. Cette méthode est l'implémentation C # de la solution Java de cette même question publiée sur Stack Overflow, ici .

/// <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";
}
masterwok
la source