C# 转换;“1.5TB”&引用;500MB“;转换为单个文件大小单位
我希望允许用户使用任何标准后缀(如TB、MB、GB)输入文件大小 我希望以一种可以将它们与文件夹大小进行比较的方式获取值 这个想法是要有一个程序,当一个文件夹超过一定的大小时会发出警告,大小由用户输入的字符串决定C# 转换;“1.5TB”&引用;500MB“;转换为单个文件大小单位,c#,.net,byte,C#,.net,Byte,我希望允许用户使用任何标准后缀(如TB、MB、GB)输入文件大小 我希望以一种可以将它们与文件夹大小进行比较的方式获取值 这个想法是要有一个程序,当一个文件夹超过一定的大小时会发出警告,大小由用户输入的字符串决定 在.net framework中是否有内置的东西允许我解析字符串,例如1.5TB、400GB、1.9GB和0.5KB?我在.net framework中找不到类似的功能,所以我想这取决于您来实现它 我认为,将字符串拆分为数字值,并将点(或逗号,比如国际逗号)作为第一部分,将KB/MB/
在.net framework中是否有内置的东西允许我解析字符串,例如
1.5TB
、400GB
、1.9GB
和0.5KB
?我在.net framework中找不到类似的功能,所以我想这取决于您来实现它
我认为,将字符串拆分为数字值,并将点(或逗号,比如国际逗号)作为第一部分,将KB/MB/etc提取为第二部分,然后手动解析每个部分将是一种可行的方法 这是一个简单的例子 这样的代码是一个简单的开始,您可能需要处理更多的情况,并考虑大小写的差异(例如,
Gb
vsGb
)
从上下文和表达式的定义开始:
public class FileSizeContext
{
private string input;
private long output;
public FileSizeContext(string input)
{
this.Input = input;
}
public string Input { get; set; }
public long Output { get; set; }
}
public abstract class FileSizeExpression
{
public abstract void Interpret(FileSizeContext value);
}
然后定义终端表达式和所有变体:
public abstract class TerminalFileSizeExpression : FileSizeExpression
{
public override void Interpret(FileSizeContext value)
{
if(value.Input.EndsWith(this.ThisPattern()))
{
double amount = double.Parse(value.Input.Replace(this.ThisPattern(),String.Empty));
var fileSize = (long)(amount*1024);
value.Input = String.Format("{0}{1}",fileSize,this.NextPattern());
value.Output = fileSize;
}
}
protected abstract string ThisPattern();
protected abstract string NextPattern();
}
public class KbFileSizeExpression : TerminalFileSizeExpression
{
protected override string ThisPattern(){return "KB";}
protected override string NextPattern() { return "bytes"; }
}
public class MbFileSizeExpression : TerminalFileSizeExpression
{
protected override string ThisPattern() { return "MB"; }
protected override string NextPattern() { return "KB"; }
}
public class GbFileSizeExpression : TerminalFileSizeExpression
{
protected override string ThisPattern() { return "GB"; }
protected override string NextPattern() { return "MB"; }
}
public class TbFileSizeExpression : TerminalFileSizeExpression
{
protected override string ThisPattern() { return "TB"; }
protected override string NextPattern() { return "GB"; }
}
然后添加一个非终端表达式(这将完成大部分工作):
实例:
编辑。从MB更改为MB(一个是正式的兆字节,另一个是兆字节)。将int改为long以适应较大的大小。简短回答:不,没有内置方法 详细回答:使用我的转换器
public class FileSizeConverter
{
private static System.Globalization.NumberFormatInfo numberFormat;
private static Dictionary<string, long> knownUnits;
static FileSizeConverter()
{
knownUnits = new Dictionary<string, long>
{
{ "", 1L }, // no unit is same as unit B(yte)
{ "B", 1L },
{ "KB", 1024L },
{ "MB", 1024L * 1024L},
{ "GB", 1024L * 1024L * 1024L},
{ "TB", 1024L * 1024L * 1024L * 1024L}
// fill rest as needed
};
// since I live in a locale where "," is the decimal separator I will enforce US number format
numberFormat = new System.Globalization.CultureInfo("en-US").NumberFormat;
}
public long Parse(string value)
{
// ignore spaces around the actual value
value = value.Trim();
string unit = ExtractUnit(value);
string sizeAsString = value.Substring(0, value.Length - unit.Length).Trim(); // trim spaces
long multiplicator = MultiplicatorForUnit(unit);
decimal size;
if (!decimal.TryParse(sizeAsString, System.Globalization.NumberStyles.Number, numberFormat, out size))
throw new ArgumentException("illegal number", "value");
return (long)(multiplicator * size);
}
private bool IsDigit(char value)
{
// we don't want to use char.IsDigit since it would accept esoterical unicode digits
if (value < '0') return false;
if (value > '9') return false;
return true;
}
private string ExtractUnit(string sizeWithUnit)
{
// start right, end at the first digit
int lastChar = sizeWithUnit.Length-1;
int unitLength = 0;
while (unitLength <= lastChar
&& sizeWithUnit[lastChar - unitLength] != ' ' // stop when a space
&& !IsDigit(sizeWithUnit[lastChar - unitLength])) // or digit is found
{
unitLength++;
}
return sizeWithUnit.Substring(sizeWithUnit.Length - unitLength).ToUpperInvariant();
}
private long MultiplicatorForUnit(string unit)
{
unit = unit.ToUpperInvariant();
if (!knownUnits.ContainsKey(unit))
throw new ArgumentException("illegal or unknown unit", "unit");
return knownUnits[unit];
}
}
公共类FileSizeConverter
{
私有静态系统.Globalization.NumberFormatInfo numberFormat;
私有静态字典知识;
静态FileSizeConverter()
{
knownUnits=新词典
{
{“”,1L},//没有一个单元与单元B(yte)相同
{“B”,1L},
{“KB”,1024L},
{“MB”,1024L*1024L},
{“GB”,1024L*1024L*1024L},
{“TB”,1024L*1024L*1024L*1024L}
//根据需要填充其余部分
};
//因为我生活在一个以“,”为小数点分隔符的地区,所以我将强制使用US数字格式
numberFormat=新系统。全球化。文化信息(“美国”)。numberFormat;
}
公共长解析(字符串值)
{
//忽略实际值周围的空格
value=value.Trim();
字符串单位=提取单位(值);
string sizeAsString=value.Substring(0,value.Length-unit.Length).Trim();//修剪空格
长乘法器=乘法器或单位(单位);
十进制大小;
if(!decimal.TryParse(sizeAsString,System.Globalization.NumberStyles.Number,numberFormat,out size))
抛出新的ArgumentException(“非法数字”、“值”);
返回(长)(乘法器*大小);
}
私有布尔IsDigit(字符值)
{
//我们不想使用char.IsDigit,因为它可以接受深奥的unicode数字
如果(值<'0')返回false;
如果(值>'9')返回false;
返回true;
}
专用字符串提取单元(字符串大小为单位)
{
//从右开始,在第一位结束
int lastChar=sizewishunit.Length-1;
int unitLength=0;
虽然(unitLength好奇,这些是base-2还是base-10前缀?BCL中没有内置任何东西,你必须自己运行。PowerShell可以做到这一点。@BoltClock,不管文件系统使用什么。我可以变得聪明,以不同的方式处理KB和KB,但这对我来说太复杂了。文件系统只使用字节。其他一切都是计算被显示文件大小的程序吓坏了。@Daniel,好吧,.net FileInfo类型调用返回的任何内容(我猜是base-2)好吧,我想可能发生了什么事,不用担心。@George现在是正则表达式时间吗?:-)那么你会有两个问题:-):-)我不确定我是否理解这个笑话,你是说你认为我会使用正则表达式,而且它太过复杂了吗?@George这对Regex
es来说(几乎)是完美的,但是,Jamie Zawinski的一句老话(我完全支持,而我对正则表达式很在行)说:有些人在遇到问题时,会思考“我知道,我会使用正则表达式。”现在他们有两个问题。你甚至不知道有多少初级程序员会这样说:“我有这个问题,我想用正则表达式解决它……但我不知道正则表达式。你能给我写这个正则表达式吗?”…所以最后这是一个笑话:-)
var ctx = new FileSizeContext("10Mb");
var parser = new FileSizeParser();
parser.Interpret(ctx);
Console.WriteLine("{0} bytes", ctx.Output); // 10485760 bytes
public class FileSizeConverter
{
private static System.Globalization.NumberFormatInfo numberFormat;
private static Dictionary<string, long> knownUnits;
static FileSizeConverter()
{
knownUnits = new Dictionary<string, long>
{
{ "", 1L }, // no unit is same as unit B(yte)
{ "B", 1L },
{ "KB", 1024L },
{ "MB", 1024L * 1024L},
{ "GB", 1024L * 1024L * 1024L},
{ "TB", 1024L * 1024L * 1024L * 1024L}
// fill rest as needed
};
// since I live in a locale where "," is the decimal separator I will enforce US number format
numberFormat = new System.Globalization.CultureInfo("en-US").NumberFormat;
}
public long Parse(string value)
{
// ignore spaces around the actual value
value = value.Trim();
string unit = ExtractUnit(value);
string sizeAsString = value.Substring(0, value.Length - unit.Length).Trim(); // trim spaces
long multiplicator = MultiplicatorForUnit(unit);
decimal size;
if (!decimal.TryParse(sizeAsString, System.Globalization.NumberStyles.Number, numberFormat, out size))
throw new ArgumentException("illegal number", "value");
return (long)(multiplicator * size);
}
private bool IsDigit(char value)
{
// we don't want to use char.IsDigit since it would accept esoterical unicode digits
if (value < '0') return false;
if (value > '9') return false;
return true;
}
private string ExtractUnit(string sizeWithUnit)
{
// start right, end at the first digit
int lastChar = sizeWithUnit.Length-1;
int unitLength = 0;
while (unitLength <= lastChar
&& sizeWithUnit[lastChar - unitLength] != ' ' // stop when a space
&& !IsDigit(sizeWithUnit[lastChar - unitLength])) // or digit is found
{
unitLength++;
}
return sizeWithUnit.Substring(sizeWithUnit.Length - unitLength).ToUpperInvariant();
}
private long MultiplicatorForUnit(string unit)
{
unit = unit.ToUpperInvariant();
if (!knownUnits.ContainsKey(unit))
throw new ArgumentException("illegal or unknown unit", "unit");
return knownUnits[unit];
}
}