我如何获得一个人类可读的文件大小字节缩写使用。net ?

例子: 输入7,326,629,显示6.98 MB


当前回答

我猜你要找的是“1.4 MB”而不是“1468006字节”?

我不认为在。net中有内置的方法来做到这一点。你只需要找出哪个单元是合适的,然后格式化它。

编辑:这里有一些示例代码来做到这一点:

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

其他回答

比如@NET3的解决方案。使用shift而不是除法来测试字节的范围,因为除法占用更多的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]);
}

有一个开源项目可以做到这一点,甚至更多。

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

下面是一个自动确定单位的简明答案。

public static string ToBytesCount(this long bytes)
{
    int unit = 1024;
    string unitStr = "B";
    if (bytes < unit)
    {
        return string.Format("{0} {1}", bytes, 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);
}

“b”代表bit,“b”代表Byte,“KMGTPEZY”分别代表kilo, mega, giga, tera, peta, exa, zetta和yotta

可以将ISO/IEC80000纳入考虑范围:

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

1-liner(加上前缀常量)

const String prefixes = " KMGTPEY";
/// <summary> Returns the human-readable file size for an arbitrary, 64-bit file size. </summary>
public static String HumanSize(UInt64 bytes)
    => Enumerable
    .Range(0, prefixes.Length)
    .Where(i => bytes < 1024U<<(i*10))
    .Select(i => $"{(bytes>>(10*i-10))/1024:0.###} {prefixes[i]}B")
    .First();

或者,如果你想减少LINQ对象的分配,使用相同的for循环变量:

/// <summary>
/// Returns the human-readable file size for an arbitrary, 64-bit file size.
/// </summary>
public static String HumanSize(UInt64 bytes)
{
    const String prefixes = " KMGTPEY";
    for (var i = 0; i < prefixes.Length; i++)
        if (bytes < 1024U<<(i*10))
            return $"{(bytes>>(10*i-10))/1024:0.###} {prefixes[i]}B";

    throw new ArgumentOutOfRangeException(nameof(bytes));
}

使用日志解决问题....

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

编辑: 有人指出我漏了一门数学课。地板,所以我把它合并了。(转换。ToInt32使用舍入,而不是截断,这就是为什么需要使用Floor。)谢谢你的帮助。

Edit2: 有一些关于负大小和0字节大小的注释,所以我更新以处理这些情况。