现在我意识到您实际上正在要求使用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 IList<string> Units;
static FileSize()
{
Units = new List<string>(){
"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);
}
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");
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 IList<string> Units;
static IntToBytesExtension()
{
Units = new List<string>(){
"B", "KB", "MB", "GB", "TB"
};
}
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());
}
而且,您可以轻松地将单位和精度更改为适合您的需求:-)