C# 如何使用 .NET 以字节缩写形式获得人类可读的文件大小?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/281640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I get a human-readable file size in bytes abbreviation using .NET?
提问by Larsenal
How do I get a human-readable file size in bytes abbreviation using .NET?
如何使用 .NET 以字节缩写形式获得人类可读的文件大小?
Example: Take input 7,326,629 and display 6.98 MB
示例:输入 7,326,629 并显示 6.98 MB
采纳答案by David Thibault
This is not the most efficient way to do it, but it's easier to read if you are not familiar with log maths, and should be fast enough for most scenarios.
这不是最有效的方法,但如果您不熟悉对数数学,它更容易阅读,并且对于大多数场景应该足够快。
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]);
回答by TcKs
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 );
回答by Peter Crabtree
I assume you're looking for "1.4 MB" instead of "1468006 bytes"?
我假设您正在寻找“1.4 MB”而不是“1468006 字节”?
I don't think there is a built-in way to do that in .NET. You'll need to just figure out which unit is appropriate, and format it.
我认为 .NET 中没有内置的方法可以做到这一点。您只需要弄清楚哪个单位是合适的,并对其进行格式化。
Edit: Here's some sample code to do just that:
编辑:这是一些示例代码来做到这一点:
回答by bobwienholt
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]);
回答by Bob
[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();
}
From: http://www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html
来自:http: //www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html
回答by Constantin
One more way to skin it, without any kind of loops and with negative size support (makes sense for things like file size deltas):
另一种皮肤的方法,没有任何类型的循环和负大小支持(对于文件大小增量之类的东西很有意义):
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]);
}
}
And here is the test suite:
这是测试套件:
[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);
}
}
回答by deepee1
using Log to solve the problem....
使用Log解决问题....
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];
}
Also in c#, but should be a snap to convert. Also I rounded to 1 decimal place for readability.
同样在 c# 中,但应该很容易转换。此外,为了可读性,我四舍五入到小数点后 1 位。
Basically Determine the number of decimal places in Base 1024 and then divide by 1024^decimalplaces.
基本上确定 Base 1024 中的小数位数,然后除以 1024^decimalplaces。
And some samples of use and output:
以及一些使用和输出示例:
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: Was pointed out that I missed a math.floor, so I incorporated it. (Convert.ToInt32 uses rounding, not truncating and that's why Floor is necessary.) Thanks for the catch.
编辑:有人指出我错过了 math.floor,所以我合并了它。(Convert.ToInt32 使用四舍五入,而不是截断,这就是为什么 Floor 是必要的。)感谢您的帮助。
Edit2: There were a couple of comments about negative sizes and 0 byte sizes, so I updated to handle those 2 cases.
Edit2:有一些关于负大小和 0 字节大小的评论,所以我更新以处理这两种情况。
回答by NET3
Mixture of all 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
}
回答by humbads
A tested and significantly optimized version of the requested function is posted here:
此处发布了所请求功能的经过测试和显着优化的版本:
C# Human Readable File Size - Optimized Function
Source code:
源代码:
// 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;
}
回答by Berend
My 2 cents:
我的 2 美分:
- The prefix for kilobyte is kB (lowercase K)
- Since these functions are for presentation purposes, one should supply a culture, for example:
string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
- Depending on the context a kilobyte can be either 1000 or 1024 bytes. The same goes for MB, GB, etc.
- 千字节的前缀是 kB(小写 K)
- 由于这些功能用于演示目的,因此应该提供一种文化,例如:
string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
- 根据上下文,千字节可以是1000 或 1024 字节。MB、GB 等也是如此。