C# 转换;“1.5TB”&引用;500MB“;转换为单个文件大小单位

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/

我希望允许用户使用任何标准后缀(如TB、MB、GB)输入文件大小

我希望以一种可以将它们与文件夹大小进行比较的方式获取值

这个想法是要有一个程序,当一个文件夹超过一定的大小时会发出警告,大小由用户输入的字符串决定


在.net framework中是否有内置的东西允许我解析字符串,例如
1.5TB
400GB
1.9GB
0.5KB

我在.net framework中找不到类似的功能,所以我想这取决于您来实现它


我认为,将字符串拆分为数字值,并将点(或逗号,比如国际逗号)作为第一部分,将KB/MB/etc提取为第二部分,然后手动解析每个部分将是一种可行的方法

这是一个简单的例子

这样的代码是一个简单的开始,您可能需要处理更多的情况,并考虑大小写的差异(例如,GbvsGb

从上下文和表达式的定义开始:

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];
    }
}