.NET มีวิธีง่ายๆในการแปลงไบต์เป็น KB, MB, GB ฯลฯ หรือไม่


112

แค่สงสัยว่า. NET มีวิธีการทำสิ่งนี้ที่สะอาดหรือไม่:

int64 x = 1000000;
string y = null;
if (x / 1024 == 0) {
    y = x + " bytes";
}
else if (x / (1024 * 1024) == 0) {
    y = string.Format("{0:n1} KB", x / 1024f);
}

ฯลฯ ...

คำตอบ:


193

นี่เป็นวิธีที่ค่อนข้างรัดกุมในการดำเนินการนี้:

static readonly string[] SizeSuffixes = 
                   { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
    if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
    if (value < 0) { return "-" + SizeSuffix(-value); } 
    if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }

    // mag is 0 for bytes, 1 for KB, 2, for MB, etc.
    int mag = (int)Math.Log(value, 1024);

    // 1L << (mag * 10) == 2 ^ (10 * mag) 
    // [i.e. the number of bytes in the unit corresponding to mag]
    decimal adjustedSize = (decimal)value / (1L << (mag * 10));

    // make adjustment when the value is large enough that
    // it would round up to 1000 or more
    if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
    {
        mag += 1;
        adjustedSize /= 1024;
    }

    return string.Format("{0:n" + decimalPlaces + "} {1}", 
        adjustedSize, 
        SizeSuffixes[mag]);
}

และนี่คือการใช้งานดั้งเดิมที่ฉันแนะนำซึ่งอาจช้าลงเล็กน้อย แต่ปฏิบัติตามได้ง่ายกว่าเล็กน้อย:

static readonly string[] SizeSuffixes = 
                  { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
    if (value < 0) { return "-" + SizeSuffix(-value); } 

    int i = 0;
    decimal dValue = (decimal)value;
    while (Math.Round(dValue, decimalPlaces) >= 1000)
    {
        dValue /= 1024;
        i++;
    }

    return string.Format("{0:n" + decimalPlaces + "} {1}", dValue, SizeSuffixes[i]);
}

Console.WriteLine(SizeSuffix(100005000L));

สิ่งหนึ่งที่ควรคำนึงถึง - ในรูปแบบ SI "กิโล" มักจะใช้ตัวพิมพ์เล็ก k ในขณะที่หน่วยขนาดใหญ่ทั้งหมดใช้อักษรตัวใหญ่ Windows ใช้ KB, MB, GB ดังนั้นฉันจึงใช้ KB ด้านบน แต่คุณอาจพิจารณา kB แทน


ผู้ถามกำลังมองหาทศนิยม 1 ตำแหน่งเท่านั้น คุณช่วยยกตัวอย่างอินพุตที่สร้างเอาต์พุตที่ไม่ถูกต้องได้ไหม
JLRishe

2
ตอนนี้ทั้งสองตัวอย่างใช้การแบ่งจุดลอยตัวดังนั้นจึงน่ากังวลน้อยกว่ามากเกี่ยวกับข้อผิดพลาดในการปัดเศษ
JLRishe

ขอบคุณสิ่งที่ฉันกำลังมองหา (การนำไปใช้ครั้งที่ 2)
snapplex

1
การใช้งานที่เรียบร้อยมาก โปรดทราบว่าหากคุณส่งค่า 0 ไปยังฟังก์ชันนี้จะทำให้เกิด IndexOutOfRangeException ฉันตัดสินใจเพิ่มการif (value == 0) { return "0"; }ตรวจสอบภายในฟังก์ชัน
bounav

คุณสามารถระบุกรณีที่ขนาดไฟล์ <0 ได้หรือไม่? สำหรับฉันมันดูแปลก ๆ ...
Ruslan F.

86

ชำระเงินไลบรารีByteSize เป็นSystem.TimeSpanไบต์!

จัดการการแปลงและการจัดรูปแบบให้คุณ

var maxFileSize = ByteSize.FromKiloBytes(10);
maxFileSize.Bytes;
maxFileSize.MegaBytes;
maxFileSize.GigaBytes;

นอกจากนี้ยังทำการแทนค่าสตริงและการแยกวิเคราะห์

// ToString
ByteSize.FromKiloBytes(1024).ToString(); // 1 MB
ByteSize.FromGigabytes(.5).ToString();   // 512 MB
ByteSize.FromGigabytes(1024).ToString(); // 1 TB

// Parsing
ByteSize.Parse("5b");
ByteSize.Parse("1.55B");

6
ใช้งานง่ายและเข้าใจและใช้ได้กับ. Net 4.0 ขึ้นไป
The Joker

34
ควรรวมไว้เป็นส่วนหนึ่งของ. NET framework
helios456

ปัญหาเดียวที่ฉันเห็นคือวิธีการแปลงใช้ได้เฉพาะจากที่ไม่ใช่ไบต์เป็นไบต์ แต่ไม่มีวิธีอื่น
SuperJMN

@SuperJMN คุณหมายถึงอะไรไม่ใช่ไบต์? ชอบบิต? มีวิธีการ. FromBits ที่คุณสามารถใช้ได้
Omar

1
หากแหล่งข้อมูลของคุณเป็นอย่างอื่นที่ไม่ใช่ "ไบต์" และคุณต้องสามารถแปลงเป็นอะไรก็ได้ ... นี่คือไลบรารีที่คุณควรใช้
James Blake

38

เนื่องจากคนอื่นโพสต์วิธีการของพวกเขาฉันคิดว่าฉันจะโพสต์วิธีการขยายที่ฉันมักจะใช้สำหรับสิ่งนี้:

แก้ไข: เพิ่มตัวแปร int / long ... และแก้ไขการพิมพ์ผิด copypasta ...

public static class Ext
{
    private const long OneKb = 1024;
    private const long OneMb = OneKb * 1024;
    private const long OneGb = OneMb * 1024;
    private const long OneTb = OneGb * 1024;

    public static string ToPrettySize(this int value, int decimalPlaces = 0)
    {
        return ((long)value).ToPrettySize(decimalPlaces);
    }

    public static string ToPrettySize(this long value, int decimalPlaces = 0)
    {
        var asTb = Math.Round((double)value / OneTb, decimalPlaces);
        var asGb = Math.Round((double)value / OneGb, decimalPlaces);
        var asMb = Math.Round((double)value / OneMb, decimalPlaces);
        var asKb = Math.Round((double)value / OneKb, decimalPlaces);
        string chosenValue = asTb > 1 ? string.Format("{0}Tb",asTb)
            : asGb > 1 ? string.Format("{0}Gb",asGb)
            : asMb > 1 ? string.Format("{0}Mb",asMb)
            : asKb > 1 ? string.Format("{0}Kb",asKb)
            : string.Format("{0}B", Math.Round((double)value, decimalPlaces));
        return chosenValue;
    }
}

โปรดทราบว่า b โดยทั่วไปแล้วตัวพิมพ์เล็กสามารถหมายถึงบิตมากกว่าไบต์ :-) en.wikipedia.org/wiki/Data-rate_units#Kilobit_per_second
SharpC

32

ฉันจะแก้ปัญหาได้โดยใช้Extension methods, Math.Powฟังก์ชั่นและEnums:

public static class MyExtension
{
    public enum SizeUnits
    {
        Byte, KB, MB, GB, TB, PB, EB, ZB, YB
    }

    public static string ToSize(this Int64 value, SizeUnits unit)
    {
        return (value / (double)Math.Pow(1024, (Int64)unit)).ToString("0.00");
    }
}

และใช้มันเช่น:

string h = x.ToSize(MyExtension.SizeUnits.KB);

3
วิธีแก้สวยหรู!
yossico

1
ฉันใช้ความคิดของคุณเพื่อสร้างสิ่งที่กำหนดหน่วยโดยอัตโนมัติ +1
Louis Somers

2
นั่นเป็นวิธีการแก้ปัญหาที่สวยงามมากซึ่งสะอาดกว่ามากและถือว่าเป็นโซลูชันที่ได้รับอนุมัติ อย่างไรก็ตามการพูดอย่างเคร่งครัดตามค่า enum ควรเป็นไปตามกำลังของ 1,000 เช่นไม่ใช่ 1024 ( en.wikipedia.org/wiki/Terabyte ) รหัส ... สตริงคงที่สาธารณะ ToSize (ค่ายาวนี้หน่วยหน่วย) => $ "{value / Math.Pow (1000, (long) unit): F2} {unit ToString ()}";
หยุด

6

คำตอบที่ได้รับการโหวตมากที่สุดฉบับย่อมีปัญหาเกี่ยวกับค่าวัณโรค

ฉันปรับให้เหมาะสมเพื่อจัดการกับค่า tb และยังไม่มีลูปและยังเพิ่มข้อผิดพลาดเล็กน้อยในการตรวจสอบค่าลบ นี่คือวิธีแก้ปัญหาของฉัน:

static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(long value, int decimalPlaces = 0)
{
    if (value < 0)
    {
        throw new ArgumentException("Bytes should not be negative", "value");
    }
    var mag = (int)Math.Max(0, Math.Log(value, 1024));
    var adjustedSize = Math.Round(value / Math.Pow(1024, mag), decimalPlaces);
    return String.Format("{0} {1}", adjustedSize, SizeSuffixes[mag]);
}

1
ปัญหาที่ระบุซึ่งมีค่ามากไม่ควรปรากฏในคำตอบที่ยอมรับอีกต่อไป
JLRishe

5

ไม่ส่วนใหญ่เป็นเพราะความต้องการเฉพาะและมีรูปแบบที่เป็นไปได้มากเกินไป (มันคือ "KB", "Kb" หรือ "Ko" เป็นเมกะไบต์ 1024 * 1024 ไบต์หรือ 1024 * 1,000 ไบต์ใช่หรือไม่บางแห่งใช้สิ่งนั้น!)


1
+1 - อ้างอิงจาก Wikipedia kb => 1,000 ไบต์และ KiB => 1024 ไบต์
Peter Majeed

5

นี่คือตัวเลือกที่ง่ายต่อการขยายมากกว่าของคุณ แต่ไม่มีไม่มีในไลบรารีเอง

private static List<string> suffixes = new List<string> { " B", " KB", " MB", " GB", " TB", " PB" };
public static string Foo(int number)
{
    for (int i = 0; i < suffixes.Count; i++)
    {
        int temp = number / (int)Math.Pow(1024, i + 1);
        if (temp == 0)
            return (number / (int)Math.Pow(1024, i)) + suffixes[i];
    }
    return number.ToString();
}

4
    private string GetFileSize(double byteCount)
    {
        string size = "0 Bytes";
        if (byteCount >= 1073741824.0)
            size = String.Format("{0:##.##}", byteCount / 1073741824.0) + " GB";
        else if (byteCount >= 1048576.0)
            size = String.Format("{0:##.##}", byteCount / 1048576.0) + " MB";
        else if (byteCount >= 1024.0)
            size = String.Format("{0:##.##}", byteCount / 1024.0) + " KB";
        else if (byteCount > 0 && byteCount < 1024.0)
            size = byteCount.ToString() + " Bytes";

        return size;
    }

    private void btnBrowse_Click(object sender, EventArgs e)
    {
        if (openFile1.ShowDialog() == DialogResult.OK)
        {
            FileInfo thisFile = new FileInfo(openFile1.FileName);

            string info = "";

            info += "File: " + Path.GetFileName(openFile1.FileName);
            info += Environment.NewLine;
            info += "File Size: " + GetFileSize((int)thisFile.Length);

            label1.Text = info;
        }
    }

นี่เป็นวิธีหนึ่งที่ทำได้เช่นกัน (หมายเลข 1073741824.0 มาจาก 1024 * 1024 * 1024 aka GB)


3

@ Servy คำตอบนั้นดีและรวบรัด ฉันคิดว่ามันจะง่ายกว่านี้ไหม

private static string[] suffixes = new [] { " B", " KB", " MB", " GB", " TB", " PB" };

public static string ToSize(double number, int precision = 2)
{
    // unit's number of bytes
    const double unit = 1024;
    // suffix counter
    int i = 0;
    // as long as we're bigger than a unit, keep going
    while(number > unit)
    {
        number /= unit;
        i++;
    }
    // apply precision and current suffix
    return Math.Round(number, precision) + suffixes[i];
}

3

จากโซลูชันที่หรูหราของ NeverHopeless:

private static readonly KeyValuePair<long, string>[] Thresholds = 
{
    // new KeyValuePair<long, string>(0, " Bytes"), // Don't devide by Zero!
    new KeyValuePair<long, string>(1, " Byte"),
    new KeyValuePair<long, string>(2, " Bytes"),
    new KeyValuePair<long, string>(1024, " KB"),
    new KeyValuePair<long, string>(1048576, " MB"), // Note: 1024 ^ 2 = 1026 (xor operator)
    new KeyValuePair<long, string>(1073741824, " GB"),
    new KeyValuePair<long, string>(1099511627776, " TB"),
    new KeyValuePair<long, string>(1125899906842620, " PB"),
    new KeyValuePair<long, string>(1152921504606850000, " EB"),

    // These don't fit into a int64
    // new KeyValuePair<long, string>(1180591620717410000000, " ZB"), 
    // new KeyValuePair<long, string>(1208925819614630000000000, " YB") 
};

/// <summary>
/// Returns x Bytes, kB, Mb, etc... 
/// </summary>
public static string ToByteSize(this long value)
{
    if (value == 0) return "0 Bytes"; // zero is plural
    for (int t = Thresholds.Length - 1; t > 0; t--)
        if (value >= Thresholds[t].Key) return ((double)value / Thresholds[t].Key).ToString("0.00") + Thresholds[t].Value;
    return "-" + ToByteSize(-value); // negative bytes (common case optimised to the end of this routine)
}

อาจจะมีความคิดเห็นมากเกินไป แต่ฉันมักจะทิ้งไว้เพื่อป้องกันไม่ให้ตัวเองทำผิดพลาดซ้ำในการเยี่ยมครั้งต่อ ๆ ไป ...


2

ไม่

แต่คุณสามารถใช้งานได้เช่นนี้

    static double ConvertBytesToMegabytes(long bytes)
    {
    return (bytes / 1024f) / 1024f;
    }

    static double ConvertKilobytesToMegabytes(long kilobytes)
    {
    return kilobytes / 1024f;
    }

ตรวจสอบวิธีการแปลงไฟล์ขนาดไบต์เป็นเมกะหรือกิกะไบต์อย่างถูกต้อง?


1

ฉันได้รวมคำตอบบางส่วนไว้ที่นี่เป็นสองวิธีที่ได้ผลดี วิธีที่สองด้านล่างจะแปลงจากสตริงไบต์ (เช่น 1.5.1 GB) กลับไปเป็นไบต์ (เช่น 1621350140) เป็นค่าประเภทยาว ฉันหวังว่านี่จะเป็นประโยชน์สำหรับผู้อื่นที่กำลังมองหาวิธีการแปลงไบต์เป็นสตริงและกลับเป็นไบต์

public static string BytesAsString(float bytes)
{
    string[] suffix = { "B", "KB", "MB", "GB", "TB" };
    int i;
    double doubleBytes = 0;

    for (i = 0; (int)(bytes / 1024) > 0; i++, bytes /= 1024)
    {
        doubleBytes = bytes / 1024.0;
    }

    return string.Format("{0:0.00} {1}", doubleBytes, suffix[i]);
}

public static long StringAsBytes(string bytesString)
{
    if (string.IsNullOrEmpty(bytesString))
    {
        return 0;
    }

    const long OneKb = 1024;
    const long OneMb = OneKb * 1024;
    const long OneGb = OneMb * 1024;
    const long OneTb = OneGb * 1024;
    double returnValue;
    string suffix = string.Empty;

    if (bytesString.IndexOf(" ") > 0)
    {
        returnValue = float.Parse(bytesString.Substring(0, bytesString.IndexOf(" ")));
        suffix = bytesString.Substring(bytesString.IndexOf(" ") + 1).ToUpperInvariant();
    }
    else
    {
        returnValue = float.Parse(bytesString.Substring(0, bytesString.Length - 2));
        suffix = bytesString.ToUpperInvariant().Substring(bytesString.Length - 2);
    }

    switch (suffix)
    {
        case "KB":
            {
                returnValue *= OneKb;
                break;
            }

        case "MB":
            {
                returnValue *= OneMb;
                break;
            }

        case "GB":
            {
                returnValue *= OneGb;
                break;
            }

        case "TB":
            {
                returnValue *= OneTb;
                break;
            }

        default:
            {
                break;
            }
    }

    return Convert.ToInt64(returnValue);
}

ฉันขอถามว่าทำไมคุณfloat.Parseถึงใช้double?
John_J

1

ฉันรู้ว่านี่เป็นกระทู้เก่าแล้ว แต่อาจมีคนมองหาวิธีแก้ปัญหา และนี่คือสิ่งที่ฉันใช้และวิธีที่ง่ายที่สุด

  public static string FormatFileSize(long bytes) 
    {
        var unit = 1024;
        if (bytes < unit)
        {
            return $"{bytes} B";
        }
        var exp = (int)(Math.Log(bytes) / Math.Log(unit));
        return $"{bytes / Math.Pow(unit, exp):F2} " +
               $"{("KMGTPE")[exp - 1]}B";
    }

0

เกี่ยวกับ:

public void printMB(uint sizekB)   
{
    double sizeMB = (double) sizekB / 1024;
    Console.WriteLine("Size is " + sizeMB.ToString("0.00") + "MB");
}

เช่นเรียกไลค์

printMB(123456);

จะส่งผลให้เอาต์พุต

"Size is 120,56 MB"

0

ฉันไปหาวิธีแก้ปัญหาของ JerKimballs และยกนิ้วให้ อย่างไรก็ตามฉันต้องการเพิ่ม / ชี้ให้เห็นว่านี่เป็นเรื่องของการโต้เถียงโดยรวม ในการวิจัยของฉัน (ด้วยเหตุผลอื่น) ฉันได้รับข้อมูลต่อไปนี้

เมื่อคนปกติ (ฉันเคยได้ยินว่ามีอยู่) พูดถึงกิกะไบต์พวกเขาอ้างถึงระบบเมตริกโดยที่ 1,000 ถึงกำลัง 3 จากจำนวนไบต์เดิม == จำนวนกิกะไบต์ อย่างไรก็ตามแน่นอนว่ามีมาตรฐาน IEC / JEDEC ซึ่งสรุปไว้อย่างดีในวิกิพีเดียซึ่งแทนที่จะเป็น 1,000 ยกกำลัง x ก็มี 1024 ซึ่งสำหรับอุปกรณ์จัดเก็บข้อมูลทางกายภาพ (และฉันเดาว่าตรรกะเช่น amazon และอื่น ๆ ) หมายถึง ความแตกต่างระหว่างเมตริกกับ IEC ที่เพิ่มขึ้นเรื่อย ๆ ตัวอย่างเช่น 1 TB == 1 เทราไบต์เมตริกคือ 1000 ยกกำลัง 4 แต่ IEC กำหนดจำนวนที่ใกล้เคียงกันอย่างเป็นทางการว่า 1 TiB, tebibyte เท่ากับ 1024 ถึงกำลัง 4 แต่อนิจจาในแอปพลิเคชันที่ไม่ใช่ทางเทคนิค (ฉันจะ ไปตามผู้ชม) บรรทัดฐานคือเมตริกและในแอปของฉันเองสำหรับการใช้งานภายในขณะนี้ฉันอธิบายความแตกต่างในเอกสาร แต่เพื่อจุดประสงค์ในการแสดงผลฉันไม่ได้เสนออะไรเลยนอกจากเมตริก ภายในแม้ว่าจะไม่เกี่ยวข้องในแอปของฉัน แต่ฉันเก็บเฉพาะไบต์และทำการคำนวณเพื่อแสดงผล

ในฐานะที่เป็นข้อสังเกตด้านข้างฉันพบว่ามันค่อนข้างน่าเบื่อที่ AFAIK เฟรมเวิร์ก. Net (และฉันมักจะผิดขอบคุณพลังที่มี) แม้ว่าจะอยู่ใน 4.5 ชาติก็ไม่มีอะไรเกี่ยวกับเรื่องนี้ในไลบรารีใด ๆ ภายใน ใคร ๆ ก็คาดหวังว่าไลบรารีโอเพนซอร์สบางประเภทจะเป็น NuGettable ได้ในบางจุด แต่ฉันยอมรับว่านี่เป็นเพียงเล็กน้อย ในทางกลับกัน System.IO.DriveInfo และอื่น ๆ ยังมีเฉพาะไบต์ (ตราบเท่า) ซึ่งค่อนข้างชัดเจน


0
public static class MyExtension
{
    public static string ToPrettySize(this float Size)
    {
        return ConvertToPrettySize(Size, 0);
    }
    public static string ToPrettySize(this int Size)
    {
        return ConvertToPrettySize(Size, 0);
    }
    private static string ConvertToPrettySize(float Size, int R)
    {
        float F = Size / 1024f;
        if (F < 1)
        {
            switch (R)
            {
                case 0:
                    return string.Format("{0:0.00} byte", Size);
                case 1:
                    return string.Format("{0:0.00} kb", Size);
                case 2:
                    return string.Format("{0:0.00} mb", Size);
                case 3:
                    return string.Format("{0:0.00} gb", Size);
            }
        }
        return ConvertToPrettySize(F, ++R);
    }
}

0

การเรียกซ้ำบางส่วนเป็นอย่างไร:

private static string ReturnSize(double size, string sizeLabel)
{
  if (size > 1024)
  {
    if (sizeLabel.Length == 0)
      return ReturnSize(size / 1024, "KB");
    else if (sizeLabel == "KB")
      return ReturnSize(size / 1024, "MB");
    else if (sizeLabel == "MB")
      return ReturnSize(size / 1024, "GB");
    else if (sizeLabel == "GB")
      return ReturnSize(size / 1024, "TB");
    else
      return ReturnSize(size / 1024, "PB");
  }
  else
  {
    if (sizeLabel.Length > 0)
      return string.Concat(size.ToString("0.00"), sizeLabel);
    else
      return string.Concat(size.ToString("0.00"), "Bytes");
  }
}

จากนั้นคุณสามารถเรียกมันว่า:

ReturnSize(size, string.Empty);

0

ดังที่โพสต์ไว้ข้างต้นการเรียกซ้ำเป็นวิธีที่ชื่นชอบด้วยความช่วยเหลือของลอการิทึม

ฟังก์ชันต่อไปนี้มี 3 อาร์กิวเมนต์: อินพุตข้อ จำกัด มิติของเอาต์พุตนั่นคืออาร์กิวเมนต์ที่สาม

int ByteReDim(unsigned long ival, int constraint, unsigned long *oval)
{
    int base = 1 + (int) log10(ival);

    (*oval) = ival;
    if (base > constraint) {
        (*oval) = (*oval) >> 10;
        return(1 + ByteReDim((*oval), constraint, oval));
    } else
        return(0);
}

ตอนนี้เรามาแปลงแรม 12GB ในหลาย ๆ หน่วย:

int main(void)
{
    unsigned long RAM;
    int unit; // index of below symbols array
    char symbol[5] = {'B', 'K', 'M', 'G', 'T'};

    unit = ByteReDim(12884901888, 12, &RAM);
    printf("%lu%c\n", RAM, symbol[unit]); // output is 12884901888B

    unit = ByteReDim(12884901888, 9, &RAM);
    printf("%lu%c\n", RAM, symbol[unit]); // output is 12582912K

    unit = ByteReDim(12884901888, 6, &RAM);
    printf("%lu%c\n", RAM, symbol[unit]); // output is 12288M

    unit = ByteReDim(12884901888, 3, &RAM);
    printf("%lu%c\n", RAM, symbol[unit]); // output is 12G
}

0

ฉันใช้สิ่งนี้สำหรับ Windows (คำนำหน้าไบนารี):

static readonly string[] BinaryPrefix = { "bytes", "KB", "MB", "GB", "TB" }; // , "PB", "EB", "ZB", "YB"
string GetMemoryString(double bytes)
{
    int counter = 0;
    double value = bytes;
    string text = "";
    do
    {
        text = value.ToString("0.0") + " " + BinaryPrefix[counter];
        value /= 1024;
        counter++;
    }
    while (Math.Floor(value) > 0 && counter < BinaryPrefix.Length);
    return text;
}

0

ฉันได้รวมสิ่งนี้ (โดยมีการปรับเปลี่ยนเพียงเล็กน้อยหรือไม่มีเลย) ใน UWP DataBinding Converter สำหรับโครงการของฉันและคิดว่ามันอาจมีประโยชน์กับผู้อื่นด้วย

รหัสคือ:

using System;
using System.Text;
using Windows.UI.Xaml.Data;

namespace MyApp.Converters
{
    public class ByteSizeConverter : IValueConverter
    {
        static readonly string[] sSizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

        // The number of decimal places the formatter should include in the scaled output - default 1dp
        public int DecimalPlaces { get; set; } = 1;

        public object Convert(object value, Type targetType, object parameter, string language)
        {
            Int64 intVal = System.Convert.ToInt64(value);

            return SizeSuffix(intVal);
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            // TODO: Parse string into number and suffix
            //       Scale number by suffix multiplier to get bytes
            throw new NotImplementedException();
        }

        string SizeSuffix(Int64 value)
        {
            if (this.DecimalPlaces < 0) { throw new ArgumentOutOfRangeException(String.Format("DecimalPlaces = {0}", this.DecimalPlaces)); }
            if (value < 0) { return "-" + SizeSuffix(-value); }
            if (value == 0) { return string.Format("{0:n" + this.DecimalPlaces + "} bytes", 0); }

            // magnitude is 0 for bytes, 1 for KB, 2, for MB, etc.
            int magnitude = (int)Math.Log(value, 1024);
            // clip magnitude - only 8 values currently supported, this prevents out-of-bounds exception
            magnitude = Math.Min(magnitude, 8);

            // 1L << (magnitude * 10) == 2 ^ (10 * magnitude) [i.e. the number of bytes in the unit corresponding to magnitude]
            decimal adjustedSize = (decimal)value / (1L << (magnitude * 10));

            // make adjustment when the value is large enough that it would round up to 1000 or more
            if (Math.Round(adjustedSize, this.DecimalPlaces) >= 1000)
            {
                magnitude += 1;
                adjustedSize /= 1024;
            }

            return String.Format("{0:n" + this.DecimalPlaces + "} {1}", adjustedSize, sSizeSuffixes[magnitude]);
        }
    }
}

ในการใช้งานให้เพิ่มทรัพยากรในเครื่องไปยัง UserControl หรือ Page XAML ของคุณ:

<UserControl.Resources>
    <converters:ByteSizeConverter x:Key="ByteFormat" DecimalPlaces="3" />
</UserControl.Resources>

อ้างอิงในเทมเพลตการผูกข้อมูลหรืออินสแตนซ์การผูกข้อมูล:

<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center"
    Text="{x:Bind MyItem.FileSize_bytes, Mode=OneWay, Converter={StaticResource ByteFormat}}" />

และเฮ้ presto ความมหัศจรรย์เกิดขึ้น


0

https://github.com/logary/logary/blob/master/src/Logary/DataModel.fs#L832-L837

let scaleBytes (value : float) : float * string =
    let log2 x = log x / log 2.
    let prefixes = [| ""; "Ki"; "Mi"; "Gi"; "Ti"; "Pi" |] // note the capital K and the 'i'
    let index = int (log2 value) / 10
    1. / 2.**(float index * 10.),
sprintf "%s%s" prefixes.[index] (Units.symbol Bytes)

(การปฏิเสธความรับผิด: ฉันเขียนรหัสนี้แม้กระทั่งรหัสในลิงค์!)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.