我如何获得一个人类可读的文件大小字节缩写使用。net ?
例子: 输入7,326,629,显示6.98 MB
我如何获得一个人类可读的文件大小字节缩写使用。net ?
例子: 输入7,326,629,显示6.98 MB
当前回答
使用日志解决问题....
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字节大小的注释,所以我更新以处理这些情况。
其他回答
比如@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]);
}
这里没有什么东西完全符合我的需要,我根据这个线程制作了我自己的,所以这里是我的长扩展,允许您根据标准选择格式要求。
绝对不是最快的,但很灵活。支持EB/EiB。
// <summary>
/// <paramref name="byteCount"/> The original size in bytes ( 8 bits )
/// <paramref name="notationFormat"/> is supported in the following ways:
/// [ 'B' / 'b' : Binary : Kilobyte (KB) is 1024 bytes, Megabyte (MB) is 1048576 bytes, etc ]
/// [ 'I' / 'i' : IEC: Kibibyte (KiB) is 1024 bytes, Mebibyte (MiB) is 1048576 bytes, etc ]
/// [ 'D' / 'd' : Decimal : Kilobyte (KB) is 1000 bytes, Megabyte (MB) is 1000000 bytes, etc ]
/// </summary>
public static string ToDataSizeString( this long byteCount, char notationFormat = 'b' )
{
char[] supportedFormatChars = { 'b', 'i', 'd' };
var lowerCaseNotationFormat = char.ToLowerInvariant( notationFormat );
// Stop shooting holes in my ship!
if ( !supportedFormatChars.Contains( lowerCaseNotationFormat ) )
{
throw new ArgumentException( $"notationFormat argument '{notationFormat}' not supported" );
}
long ebLimit = 1152921504606846976;
long pbLimit = 1125899906842624;
long tbLimit = 1099511627776;
long gbLimit = 1073741824;
long mbLimit = 1048576;
long kbLimit = 1024;
var ebSuffix = "EB";
var pbSuffix = "PB";
var tbSuffix = "TB";
var gbSuffix = "GB";
var mbSuffix = "MB";
var kbSuffix = "KB";
var bSuffix = " B";
switch ( lowerCaseNotationFormat )
{
case 'b':
// Sweet as
break;
case 'i':
// Limits stay the same, suffixes need changed
ebSuffix = "EiB";
pbSuffix = "PiB";
tbSuffix = "TiB";
gbSuffix = "GiB";
mbSuffix = "MiB";
kbSuffix = "KiB";
bSuffix = " B";
break;
case 'd':
// Suffixes stay the same, limits need changed
ebLimit = 1000000000000000000;
pbLimit = 1000000000000000;
tbLimit = 1000000000000;
gbLimit = 1000000000;
mbLimit = 1000000;
kbLimit = 1000;
break;
default:
// Should have already Excepted, but hey whatever
throw new ArgumentException( $"notationFormat argument '{notationFormat}' not supported" );
}
string fileSizeText;
// Exa/Exbi sized
if ( byteCount >= ebLimit )
{
fileSizeText = $"{( (double)byteCount / ebLimit ):N1} {ebSuffix}";
}
// Peta/Pebi sized
else if ( byteCount >= pbLimit )
{
fileSizeText = $"{( (double)byteCount / pbLimit ):N1} {pbSuffix}";
}
// Tera/Tebi sized
else if ( byteCount >= tbLimit )
{
fileSizeText = $"{( (double)byteCount / tbLimit ):N1} {tbSuffix}";
}
// Giga/Gibi sized
else if ( byteCount >= gbLimit )
{
fileSizeText = $"{( (double)byteCount / gbLimit ):N1} {gbSuffix}";
}
// Mega/Mibi sized
else if ( byteCount >= mbLimit )
{
fileSizeText = $"{( (double)byteCount / mbLimit ):N1} {mbSuffix}";
}
// Kilo/Kibi sized
else if ( byteCount >= kbLimit )
{
fileSizeText = $"{( (double)byteCount / kbLimit ):N1} {kbSuffix}";
}
// Byte sized
else
{
fileSizeText = $"{byteCount} {bSuffix}";
}
return fileSizeText;
}
为了获得人类可读的字符串,就像用户在Windows环境中习惯的那样,你应该使用StrFormatByteSize():
using System.Runtime.InteropServices;
...
private long mFileSize;
[DllImport("Shlwapi.dll", CharSet = CharSet.Auto)]
public static extern int StrFormatByteSize(
long fileSize,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder buffer,
int bufferSize);
public string HumanReadableFileSize
{
get
{
var sb = new StringBuilder(20);
StrFormatByteSize(mFileSize, sb, 20);
return sb.ToString();
}
}
我在这里找到了这个: http://csharphelper.com/blog/2014/07/format-file-sizes-in-kb-mb-gb-and-so-forth-in-c/
下面是@ deepe1的BigInteger版本的答案,它绕过了long的大小限制(因此支持yottabyte和理论上的任何后面的限制):
public static string ToBytesString(this BigInteger byteCount, string format = "N3")
{
string[] suf = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB" };
if (byteCount.IsZero)
{
return $"{0.0.ToString(format)} {suf[0]}";
}
var abs = BigInteger.Abs(byteCount);
var place = Convert.ToInt32(Math.Floor(BigInteger.Log(abs, 1024)));
var pow = Math.Pow(1024, place);
// since we need to do this with integer math, get the quotient and remainder
var quotient = BigInteger.DivRem(abs, new BigInteger(pow), out var remainder);
// convert the remainder to a ratio and add both back together as doubles
var num = byteCount.Sign * (Math.Floor((double)quotient) + ((double)remainder / pow));
return $"{num.ToString(format)} {suf[place]}";
}
使用日志解决问题....
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字节大小的注释,所以我更新以处理这些情况。