转换为1.5TB", &;500MB"转换为文件大小的单个单位

本文关键字:转换 quot 单个 单位 文件大小 5TB 500MB | 更新日期: 2023-09-27 18:08:04

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

我想以一种可以将它们与文件夹大小进行比较的方式获得值。

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

是否有任何内置到。net框架,允许我解析字符串,如1.5TB, 400GB, 1.9GB0.5KB ?

转换为1.5TB", &;500MB"转换为文件大小的单个单位

这是一个很好的简单解释器候选。

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

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

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

然后定义你的终端表达式,a和所有的变体:

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

然后添加一个非终结符表达式(这完成了大部分工作):

public class FileSizeParser : FileSizeExpression
{
    private List<FileSizeExpression> expressionTree = new List<FileSizeExpression>()
                                                  {
                                                      new TbFileSizeExpression(),
                                                      new GbFileSizeExpression(),
                                                      new MbFileSizeExpression(),
                                                      new KbFileSizeExpression()
                                                  };
    public override void Interpret(FileSizeContext value)
    {
        foreach (FileSizeExpression exp in expressionTree)
        {
            exp.Interpret(value);
        }
    }
}

最后,下面是客户端代码:

var ctx = new FileSizeContext("10Mb");
var parser = new FileSizeParser();
parser.Interpret(ctx);
Console.WriteLine("{0} bytes", ctx.Output); // 10485760 bytes

实例:http://rextester.com/rundotnet?code=WMGOQ13650

编辑。由MB改为MB(一个是兆字节,另一个是兆比特)。

简短的回答:没有,没有内置的方法。

长话短说:用我的转换器。

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

EDIT:这里是现场演示:http://rextester.com/rundotnet?code=BQYCB2587(感谢@Jamiec提供的链接,非常方便在线运行c#源代码)

我在。net框架中找不到这样的功能,所以我想这取决于你来实现它。

我认为分割字符串的数值和点(或逗号,认为国际)作为第一部分,提取KB/MB等作为第二部分,并手动解析每个部分将是可行的方法。