簡體   English   中英

將“ 1.5TB”,“ 500MB”轉換為單個文件大小單位

[英]Convert “1.5TB”, “500MB” into a single unit of file size

我想允許用戶使用任何標准后綴(例如TB,MB,GB)輸入文件大小

我想以一種可以將它們與文件夾大小進行比較的方式來獲取值。

想法是要有一個程序來警告文件夾是否超過某個特定大小,該大小由用戶輸入的字符串決定。

.net框架中是否內置任何可讓我解析諸如1.5TB400GB1.9GB0.5KB

這對於簡單的口譯員來說是一個很好的選擇。

像這樣的代碼是一個簡單的開始,您可能需要處理更多的情況,並考慮大小寫差異(例如Gb vs GB )。

您從上下文和表達式的定義開始:

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

然后添加一個非終止表達式(這完成了大部分工作):

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(一個正式為MegaByte,另一個為MegaBit)。 將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];
    }
}

編輯 :這是現場演示: http ://rextester.com/rundotnet?code=BQYCB2587(感謝@Jamiec提供的鏈接,非常方便在線運行C#源代碼)

我無法通過快速的Google搜索在.NET Framework中找到這樣的功能,所以我想這取決於您實現它。

我認為將數字值和點(或逗號,認為是國際的)上的字符串拆分為第一部分,然后將KB / MB / etc提取為第二部分,然后手動解析每個部分將是解決方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM