[英]Convert “1.5TB”, “500MB” into a single unit of file size
我想允許用戶使用任何標准后綴(例如TB,MB,GB)輸入文件大小
我想以一種可以將它們與文件夾大小進行比較的方式來獲取值。
想法是要有一個程序來警告文件夾是否超過某個特定大小,該大小由用戶輸入的字符串決定。
.net框架中是否內置任何可讓我解析諸如1.5TB
, 400GB
, 1.9GB
和0.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.