如何获得一个可读的文件大小以字节缩写使用.NET?
如何获得一个可读的文件大小以字节缩写使用.NET?
例如 :input7,326,629并显示6.98 MB
这不是最有效的方法,但是如果你不熟悉日志math,读起来更容易,对大多数场景来说应该足够快。
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]);
用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]; }
也在C#中,但应该是一个快速转换。 另外,为了便于阅读,我四舍五入到小数点后一位
基本上确定在基地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
编辑:被指出,我错过了一个math.floor,所以我把它合并。 (Convert.ToInt32使用四舍五入,而不是截断,这就是为什么地板是必要的。)感谢收获。
编辑2:有几个关于负尺寸和0字节大小的评论,所以我更新了处理这两个案例。
[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(); }
来自: http : //www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html
经过testing和显着优化的请求function的版本张贴在这里:
C#人可读文件大小 – 优化function
源代码:
// Returns the human-readable file size for an arbitrary, 64-bit file size // The default format is "0.### XB", eg "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; }
还有一种方法可以去除它,没有任何forms的循环和负面的尺寸支持(对于像文件大小增量这样的东西是有意义的):
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]); } }
这里是testing套件:
[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); } }
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 );
我喜欢使用下面的方法(它支持高达TB,这在大多数情况下是足够的,但是可以很容易地扩展):
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}"; }
请记住,这是为C#6.0(2015)编写的,因此可能需要对早期版本进行一些编辑。
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]);
检出ByteSize库。 这是字节的System.TimeSpan
!
它处理您的转换和格式。
var maxFileSize = ByteSize.FromKiloBytes(10); maxFileSize.Bytes; maxFileSize.MegaBytes; maxFileSize.GigaBytes;
它也做string表示和parsing。
// 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");
所有解决scheme的混合物:-)
/// <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 }
有一个开源项目可以做到这一点,更多。
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
如果您尝试按照Windows资源pipe理器的详细信息视图中显示的大小进行匹配,则这是您需要的代码:
[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(); }
这不仅会与资源pipe理器完全匹配,而且还会提供为您翻译的string,并匹配Windows版本中的差异(例如在Win10中,K = 1000与以前版本K = 1024)。
我假设你正在寻找“1.4 MB”而不是“1468006字节”?
我不认为有一个内置的方式来在.NET中做到这一点。 你需要找出哪个单位是适当的,并格式化。
编辑:这里有一些示例代码来做到这一点:
我的2美分:
- 千字节的前缀是kB(小写字母K)
- 由于这些函数是为了演示目的,所以应该提供一种文化,例如:
string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
- 根据上下文,千字节可以是1000或1024字节 。 MB,GB等也是如此
还有一种方法,它是值得的。 我喜欢上面引用的@humbads优化的解决scheme,所以已经复制了原理,但是我已经实现了一点点不同。
我想这是否应该是一个扩展方法是有争议的(因为并不是所有的long都必须是字节大小),但是我喜欢它们,而且当我下一次需要的时候,我可以find方法的地方!
关于这个单位,我觉得我以前从来没有说过“Kibibyte”或“Mebibyte”这个词,虽然我对这样的强制性标准而不是进化标准持怀疑态度,但是我认为这样可以避免长期的混淆。
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); } }
像@ NET3的解决scheme。 使用shift而不是division来testingbytes
的范围,因为division需要更多的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]); }
如何recursion:
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"); } }
那你叫它:
return ReturnSize(size, string.Empty);