有没有简单的方法来创建一个使用的类 IFormatProvider它写出一个用户友好的文件大小?
public static string GetFileSizeString(string filePath) { FileInfo info = new FileInfo(@"c:\windows\notepad.exe"); long size = info.Length; string sizeString = size.ToString(FileSizeFormatProvider); // This is where the class does its magic... }
它应该导致字符串格式化为" 2,5 MB "," 3,9 GB "," 670字节 "等等.
我用这个,我从网上得到它
public class FileSizeFormatProvider : IFormatProvider, ICustomFormatter { public object GetFormat(Type formatType) { if (formatType == typeof(ICustomFormatter)) return this; return null; } private const string fileSizeFormat = "fs"; private const Decimal OneKiloByte = 1024M; private const Decimal OneMegaByte = OneKiloByte * 1024M; private const Decimal OneGigaByte = OneMegaByte * 1024M; public string Format(string format, object arg, IFormatProvider formatProvider) { if (format == null || !format.StartsWith(fileSizeFormat)) { return defaultFormat(format, arg, formatProvider); } if (arg is string) { return defaultFormat(format, arg, formatProvider); } Decimal size; try { size = Convert.ToDecimal(arg); } catch (InvalidCastException) { return defaultFormat(format, arg, formatProvider); } string suffix; if (size > OneGigaByte) { size /= OneGigaByte; suffix = "GB"; } else if (size > OneMegaByte) { size /= OneMegaByte; suffix = "MB"; } else if (size > OneKiloByte) { size /= OneKiloByte; suffix = "kB"; } else { suffix = " B"; } string precision = format.Substring(2); if (String.IsNullOrEmpty(precision)) precision = "2"; return String.Format("{0:N" + precision + "}{1}", size, suffix); } private static string defaultFormat(string format, object arg, IFormatProvider formatProvider) { IFormattable formattableArg = arg as IFormattable; if (formattableArg != null) { return formattableArg.ToString(format, formatProvider); } return arg.ToString(); } }
使用的一个例子是:
Console.WriteLine(String.Format(new FileSizeFormatProvider(), "File size: {0:fs}", 100)); Console.WriteLine(String.Format(new FileSizeFormatProvider(), "File size: {0:fs}", 10000));
http://flimflan.com/blog/FileSizeFormatProvider.aspx的积分
ToString()存在问题,它期望实现IFormatProvider的NumberFormatInfo类型,但NumberFormatInfo类是密封的:(
如果您使用的是C#3.0,则可以使用扩展方法获得所需的结果:
public static class ExtensionMethods { public static string ToFileSize(this long l) { return String.Format(new FileSizeFormatProvider(), "{0:fs}", l); } }
你可以像这样使用它.
long l = 100000000; Console.WriteLine(l.ToFileSize());
希望这可以帮助.
好吧我不打算把它作为格式提供程序包装起来,而不是重新发明轮子,有一个Win32 api调用来根据我在各种应用程序中多次使用的提供字节格式化一个大小字符串.
[DllImport("Shlwapi.dll", CharSet = CharSet.Auto)] public static extern long StrFormatByteSize( long fileSize, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder buffer, int bufferSize );
所以我想你应该能够将使用它作为核心转换代码的提供者放在一起.
这里有一个链接到MSDN规范的StrFormatByteSize.
我现在意识到你实际上是在寻找可以使用String.Format()的东西 - 我想我应该在发布之前读过两次问题;-)
我不喜欢每次都必须明确传入格式提供程序的解决方案 - 从我从本文中收集到的,最好的方法是实现FileSize类型,实现IFormattable接口.
我继续实现了一个支持这个接口的结构,可以从一个整数转换.在我自己的文件相关API中,我将使用我的.FileSize属性返回FileSize实例.
这是代码:
using System.Globalization; public struct FileSize : IFormattable { private ulong _value; private const int DEFAULT_PRECISION = 2; private static IListUnits; static FileSize() { Units = new List (){ "B", "KB", "MB", "GB", "TB" }; } public FileSize(ulong value) { _value = value; } public static explicit operator FileSize(ulong value) { return new FileSize(value); } override public string ToString() { return ToString(null, null); } public string ToString(string format) { return ToString(format, null); } public string ToString(string format, IFormatProvider formatProvider) { int precision; if (String.IsNullOrEmpty(format)) return ToString(DEFAULT_PRECISION); else if (int.TryParse(format, out precision)) return ToString(precision); else return _value.ToString(format, formatProvider); } /// /// Formats the FileSize using the given number of decimals. /// public string ToString(int precision) { double pow = Math.Floor((_value > 0 ? Math.Log(_value) : 0) / Math.Log(1024)); pow = Math.Min(pow, Units.Count - 1); double value = (double)_value / Math.Pow(1024, pow); return value.ToString(pow == 0 ? "F0" : "F" + precision.ToString()) + " " + Units[(int)pow]; } }
还有一个简单的单元测试,演示了它的工作原理:
[Test] public void CanUseFileSizeFormatProvider() { Assert.AreEqual(String.Format("{0}", (FileSize)128), "128 B"); Assert.AreEqual(String.Format("{0}", (FileSize)1024), "1.00 KB"); Assert.AreEqual(String.Format("{0:0}", (FileSize)10240), "10 KB"); Assert.AreEqual(String.Format("{0:1}", (FileSize)102400), "100.0 KB"); Assert.AreEqual(String.Format("{0}", (FileSize)1048576), "1.00 MB"); Assert.AreEqual(String.Format("{0:D}", (FileSize)123456), "123456"); // You can also manually invoke ToString(), optionally with the precision specified as an integer: Assert.AreEqual(((FileSize)111111).ToString(2), "108.51 KB"); }
如您所见,FileSize类型现在可以正确格式化,并且还可以指定小数位数,以及根据需要应用常规数字格式.
我想你可以更进一步,例如允许显式格式选择,例如"{0:KB}"强制格式化为千字节.但是我会把它留在这里.
我也离开了我的初始帖子,因为那两个人不想使用格式化API ...
皮肤猫的100种方法,但这是我的方法 - 在int类型中添加扩展方法:
public static class IntToBytesExtension { private const int PRECISION = 2; private static IListUnits; static IntToBytesExtension() { Units = new List (){ "B", "KB", "MB", "GB", "TB" }; } /// /// Formats the value as a filesize in bytes (KB, MB, etc.) /// /// This value. ///Filesize and quantifier formatted as a string. public static string ToBytes(this int bytes) { double pow = Math.Floor((bytes>0 ? Math.Log(bytes) : 0) / Math.Log(1024)); pow = Math.Min(pow, Units.Count-1); double value = (double)bytes / Math.Pow(1024, pow); return value.ToString(pow==0 ? "F0" : "F" + PRECISION.ToString()) + " " + Units[(int)pow]; } }
在程序集中使用此扩展,要格式化文件大小,只需使用类似(1234567).ToBytes()的语句
以下MbUnit测试精确地阐明了输出的样子:
[Test] public void CanFormatFileSizes() { Assert.AreEqual("128 B", (128).ToBytes()); Assert.AreEqual("1.00 KB", (1024).ToBytes()); Assert.AreEqual("10.00 KB", (10240).ToBytes()); Assert.AreEqual("100.00 KB", (102400).ToBytes()); Assert.AreEqual("1.00 MB", (1048576).ToBytes()); }
您可以轻松地将单位和精度更改为适合您需要的任何内容:-)
这是我知道的格式化文件大小最简单的实现:
public string SizeText { get { var units = new[] { "B", "KB", "MB", "GB", "TB" }; var index = 0; double size = Size; while (size > 1024) { size /= 1024; index++; } return string.Format("{0:2} {1}", size, units[index]); } }
而Size是未格式化的文件大小(以字节为单位).
问候基督徒
http://www.wpftutorial.net
我的代码...感谢Shaun Austin.
[DllImport("Shlwapi.dll", CharSet = CharSet.Auto)] public static extern long StrFormatByteSize(long fileSize, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder buffer, int bufferSize); public void getFileInfo(string filename) { System.IO.FileInfo fileinfo = new FileInfo(filename); this.FileName.Text = fileinfo.Name; StringBuilder buffer = new StringBuilder(); StrFormatByteSize(fileinfo.Length, buffer, 100); this.FileSize.Text = buffer.ToString(); }