如何获得一个可读的文件大小以字节缩写使用.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 

http://humanizr.net/#bytesize

https://github.com/MehdiK/Humanizer

如果您尝试按照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中做到这一点。 你需要找出哪个单位是适当的,并格式化。

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

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

我的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);