.NET是否提供了将字节转换为KB,MB,GB等的简单方法?

Joh*_*ith 97 .net c# byte megabyte

只是想知道.NET是否提供了一种干净的方法来执行此操作:

int64 x = 1000000;
string y = null;
if (x / 1024 == 0) {
    y = x + " bytes";
}
else if (x / (1024 * 1024) == 0) {
    y = string.Format("{0:n1} KB", x / 1024f);
}
Run Code Online (Sandbox Code Playgroud)

等等...

JLR*_*she 176

这是一个相当简洁的方法:

static readonly string[] SizeSuffixes = 
                   { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
    if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
    if (value < 0) { return "-" + SizeSuffix(-value); } 
    if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }

    // mag is 0 for bytes, 1 for KB, 2, for MB, etc.
    int mag = (int)Math.Log(value, 1024);

    // 1L << (mag * 10) == 2 ^ (10 * mag) 
    // [i.e. the number of bytes in the unit corresponding to mag]
    decimal adjustedSize = (decimal)value / (1L << (mag * 10));

    // make adjustment when the value is large enough that
    // it would round up to 1000 or more
    if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
    {
        mag += 1;
        adjustedSize /= 1024;
    }

    return string.Format("{0:n" + decimalPlaces + "} {1}", 
        adjustedSize, 
        SizeSuffixes[mag]);
}
Run Code Online (Sandbox Code Playgroud)

这是我建议的原始实现,可能稍微慢一点,但更容易遵循:

static readonly string[] SizeSuffixes = 
                  { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
    if (value < 0) { return "-" + SizeSuffix(-value); } 

    int i = 0;
    decimal dValue = (decimal)value;
    while (Math.Round(dValue, decimalPlaces) >= 1000)
    {
        dValue /= 1024;
        i++;
    }

    return string.Format("{0:n" + decimalPlaces + "} {1}", dValue, SizeSuffixes[i]);
}

Console.WriteLine(SizeSuffix(100005000L));
Run Code Online (Sandbox Code Playgroud)

  • 这两个示例现在都使用浮点除法,因此对舍入错误的关注应该更少. (2认同)

Oma*_*mar 74

签出ByteSize库.这是System.TimeSpan字节!

它为您处理转换和格式.

var maxFileSize = ByteSize.FromKiloBytes(10);
maxFileSize.Bytes;
maxFileSize.MegaBytes;
maxFileSize.GigaBytes;
Run Code Online (Sandbox Code Playgroud)

它还进行字符串表示和解析.

// 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");
Run Code Online (Sandbox Code Playgroud)

  • 这应该作为.NET框架的一部分包含在内 (26认同)
  • 易于使用和理解,它适用于.Net 4.0及更高版本. (4认同)
  • 如果您的源数据不是“字节”,并且您需要能够转换为任何内容......这就是您应该使用的库。 (2认同)

Jer*_*all 35

由于其他人都在发布他们的方法,我想我会发布我通常用于此的扩展方法:

编辑:添加int/long变体...并修复了copypasta拼写错误...

public static class Ext
{
    private const long OneKb = 1024;
    private const long OneMb = OneKb * 1024;
    private const long OneGb = OneMb * 1024;
    private const long OneTb = OneGb * 1024;

    public static string ToPrettySize(this int value, int decimalPlaces = 0)
    {
        return ((long)value).ToPrettySize(decimalPlaces);
    }

    public static string ToPrettySize(this long value, int decimalPlaces = 0)
    {
        var asTb = Math.Round((double)value / OneTb, decimalPlaces);
        var asGb = Math.Round((double)value / OneGb, decimalPlaces);
        var asMb = Math.Round((double)value / OneMb, decimalPlaces);
        var asKb = Math.Round((double)value / OneKb, decimalPlaces);
        string chosenValue = asTb > 1 ? string.Format("{0}Tb",asTb)
            : asGb > 1 ? string.Format("{0}Gb",asGb)
            : asMb > 1 ? string.Format("{0}Mb",asMb)
            : asKb > 1 ? string.Format("{0}Kb",asKb)
            : string.Format("{0}B", Math.Round((double)value, decimalPlaces));
        return chosenValue;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请记住,小写 b 通常表示位而不是字节。:-) https://en.wikipedia.org/wiki/Data-rate_units#Kilobit_per_second (3认同)

Nev*_*ess 26

我会使用Extension methods,Math.Pow函数和解决它Enums:

public static class MyExtension
{
    public enum SizeUnits
    {
        Byte, KB, MB, GB, TB, PB, EB, ZB, YB
    }

    public static string ToSize(this Int64 value, SizeUnits unit)
    {
        return (value / (double)Math.Pow(1024, (Int64)unit)).ToString("0.00");
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用它像:

string h = x.ToSize(MyExtension.SizeUnits.KB);
Run Code Online (Sandbox Code Playgroud)

  • 优雅的解决方 (3认同)
  • 这是一个非常优雅的解决方案,它比批准的解决方案更简洁和简洁。但是,严格来说,基于枚举值,它应该基于 1000 的幂,即不是 1024 (https://en.wikipedia.org/wiki/Terabyte) 代码... public static string ToSize(this long value, Unit unit) =&gt; $"{value / Math.Pow(1000, (long) unit):F2}{unit.ToString()}"; (3认同)

zac*_*k15 11

我知道这已经是旧线程了。但也许有人会寻找解决方案。这是我使用的最简单的方法

public static string FormatFileSize(long bytes)
{
    var unit = 1024;
    if (bytes < unit) { return $"{bytes} B"; }

    var exp = (int)(Math.Log(bytes) / Math.Log(unit));
    return $"{bytes / Math.Pow(unit, exp):F2} {("KMGTPE")[exp - 1]}B";
}
Run Code Online (Sandbox Code Playgroud)

获取文件夹大小(例如用法)

public static long GetFolderSize(string path, string ext, bool AllDir)
{
    var option = AllDir ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
    return new DirectoryInfo(path).EnumerateFiles("*" + ext, option).Sum(file => file.Length);
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

public static void TEST()
{
    string folder = @"C:\Users\User\Videos";

    var bytes = GetFolderSize(folder, "mp4", true); //or GetFolderSize(folder, "mp4", false) to get all single folder only
    var totalFileSize = FormatFileSize(bytes);
    Console.WriteLine(totalFileSize);
}
Run Code Online (Sandbox Code Playgroud)

  • 这是这里最优雅的解决方案。 (2认同)
  • @SergeyKovalev 谢谢:)我一直在使用这个。占用CPU少,使用方便 (2认同)

Cry*_*hic 10

更新了 C# 9.0关系模式

public const long OneKB = 1024;

public const long OneMB = OneKB * OneKB;

public const long OneGB = OneMB * OneKB;

public const long OneTB = OneGB * OneKB;

public static string BytesToHumanReadable(ulong bytes)
{
    return bytes switch
    {
        (< OneKB) => $"{bytes}B",
        (>= OneKB) and (< OneMB) => $"{bytes / OneKB}KB",
        (>= OneMB) and (< OneGB) => $"{bytes / OneMB}MB",
        (>= OneGB) and (< OneTB) => $"{bytes / OneMB}GB",
        (>= OneTB) => $"{bytes / OneTB}"
        //...
    };
}
Run Code Online (Sandbox Code Playgroud)


Roe*_*mer 6

投票最多的答案的简短版本在TB值方面存在问题。

我对其进行了适当的调整,以处理tb值,并且仍然没有循环,并且还为负值添加了一些错误检查。这是我的解决方案:

static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(long value, int decimalPlaces = 0)
{
    if (value < 0)
    {
        throw new ArgumentException("Bytes should not be negative", "value");
    }
    var mag = (int)Math.Max(0, Math.Log(value, 1024));
    var adjustedSize = Math.Round(value / Math.Pow(1024, mag), decimalPlaces);
    return String.Format("{0} {1}", adjustedSize, SizeSuffixes[mag]);
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*ran 5

不是.主要是因为它具有相当小的需求,并且存在太多可能的变化.(它是"KB","Kb"还是"Ko"?是兆字节1024*1024字节,还是1024*1000字节? - 是的,有些地方使用它!)

  • 主要是这 - 诅咒硬盘制造商! (2认同)

Ser*_*rvy 5

这是一个比你更容易扩展的选项,但不是,库中没有内置的选项.

private static List<string> suffixes = new List<string> { " B", " KB", " MB", " GB", " TB", " PB" };
public static string Foo(int number)
{
    for (int i = 0; i < suffixes.Count; i++)
    {
        int temp = number / (int)Math.Pow(1024, i + 1);
        if (temp == 0)
            return (number / (int)Math.Pow(1024, i)) + suffixes[i];
    }
    return number.ToString();
}
Run Code Online (Sandbox Code Playgroud)


drz*_*aus 5

@Servy 的回答很好而且简洁。我认为它可以更简单?

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

public static string ToSize(double number, int precision = 2)
{
    // unit's number of bytes
    const double unit = 1024;
    // suffix counter
    int i = 0;
    // as long as we're bigger than a unit, keep going
    while(number > unit)
    {
        number /= unit;
        i++;
    }
    // apply precision and current suffix
    return Math.Round(number, precision) + suffixes[i];
}
Run Code Online (Sandbox Code Playgroud)