C# NET是否提供了将字节转换为KB、MB、GB等的简单方法。?

C# NET是否提供了将字节转换为KB、MB、GB等的简单方法。?,c#,.net,byte,megabyte,C#,.net,Byte,Megabyte,只是想知道.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); } static readonly string[] SizeSuffixes =

只是想知道.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);
}
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, decimalPlaces); } 
    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]);
}

等等。

不。主要是因为它是一个相当利基的需求,并且有太多可能的变化。(是“KB”、“KB”还是“Ko”?是兆字节1024*1024字节,还是1024*1000字节?--是的,有些地方使用它!)

但是你可以这样实现

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

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

另外请查看

这里有一个比您的更容易扩展的选项,但是没有,库本身没有内置任何选项

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();
}
私有静态列表后缀=新列表{“B”、“KB”、“MB”、“GB”、“TB”、“PB”};
公共静态字符串Foo(整数)
{
for(int i=0;i<后缀.Count;i++)
{
int temp=数字/(int)数学功率(1024,i+1);
如果(温度==0)
返回(number/(int)Math.Pow(1024,i))+后缀[i];
}
返回编号.ToString();
}

以下是一种相当简洁的方法:

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);
}
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, decimalPlaces); } 
    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]);
}
静态只读字符串[]大小uffixes=
{“字节”、“KB”、“MB”、“GB”、“TB”、“PB”、“EB”、“ZB”、“YB”};
静态字符串大小uffix(Int64值,int decimalPlaces=1)
{
如果(decimalPlaces<0){抛出新ArgumentOutOfRangeException(“decimalPlaces”);}
如果(值<0){return“-”+SizeSuffix(-value,decimalPlaces);}
if(value==0){return string.Format(“{0:n”+decimalPlaces+“}字节”,0);}
//mag为0表示字节,1表示KB,2表示MB,等等。
intmag=(int)Math.Log(值1024);

//1L因为其他人都在发布他们的方法,我想我应该发布我通常用于此的扩展方法:

编辑:添加了int/long变体…并修复了一个复制错误

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

我已经将这里的一些答案组合成两种非常有效的方法。下面的第二种方法将从字节字符串(如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);
}

投票最多的答案的简短版本存在TB值问题

我对其进行了适当的调整,以处理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]);
}
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)
}
static readonly string[]sizesuffix={“bytes”、“KB”、“MB”、“GB”、“TB”、“PB”、“EB”、“ZB”、“YB”};
静态字符串大小uffix(长值,整数小数位数=0)
{
如果(值<0)
{
抛出新ArgumentException(“字节不应为负数”、“值”);
}
var mag=(int)Math.Max(0,Math.Log(value,1024));
var adjustedSize=数学舍入(数值/数学功率(1024,mag),小数位数);
返回String.Format(“{0}{1}”),adjustedSize,SizeSuffix[mag]);
}
签出库。这是字节的
系统。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");
那么:

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"

我将使用
扩展方法
Math.Pow
函数和
枚举
解决它:

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);
private string GetFileSize(双字节计数)
{
字符串大小=“0字节”;
如果(字节数>=1073741824.0)
size=String.Format(“{0:###.###}”,字节数/1073741824.0)+“GB”;
else if(字节数>=1048576.0)
size=String.Format(“{0:###.###}”,字节数/1048576.0)+“MB”;
else if(字节数>=1024.0)
size=String.Format(“{0:###.###}”,字节数/1024.0)+“KB”;
else if(字节数>0&&字节数<1024.0)
大小=字节数.ToString()+“字节”;
返回大小;
}
私有无效btnBrowse\u单击(对象发送者,事件参数)
{
if(openFile1.ShowDialog()==DialogResult.OK)
{
FileInfo thisFile=newfileinfo(openFile1.FileName);
字符串信息=”;
info+=“文件:”+Path.GetFileName(openFile1.FileName);
info+=Environment.NewLine;
info+=“文件大小:”+GetFileSize((int)thisFile.Length);
标签1.Text=info;
}
}

这也是一种方法(数字1073741824.0来自1024*1024*1024 aka GB)

我选择了JerKimballs解决方案,并对此表示赞许。 然而,我想补充/指出,这确实是一个有争议的整体问题。在我的研究中(出于其他原因),我得到了以下信息

当普通人(我听说他们存在)谈到千兆字节时,他们指的是公制,其中1000是原始字节数的3的幂==千兆字节数。 然而,当然也有IEC/JEDEC标准,这在维基百科中得到了很好的总结,它不是1000到x的幂,而是1024。 这对于物理存储设备(我猜是逻辑存储设备,如amazon和其他)意味着metric和IEC之间的差异越来越大。 例如,1TB==1TB的度量值是1000乘以4的幂,但IEC官方将类似的数字定义为1TB,tebibyte表示1024乘以4的幂。 但是,唉,在非技术应用程序中(我会以观众为单位),标准是公制,在我自己的内部使用的应用程序中,目前我解释了文档中的差异。但出于显示目的,我甚至只提供公制。在内部,尽管它与我的应用程序无关,但我只存储字节并进行显示计算

作为旁注,我发现.Net框架AFAIK有点平淡无奇(我经常错了,感谢它的强大)即使是在它的4.5版本中,在任何库内部都没有包含任何关于这方面的内容。人们可能会期望某种开源库在某个时候是可以使用的,但我承认这是一个小问题。另一方面,System.IO.DriveInfo和其他库也只有字节(尽可能长),这是非常清楚的。

(免责声明:I)
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);
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);
}
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
}
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];
}
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)
}
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;
}
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.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}}" />
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";
}
public static long GetFolderSize(string path, string ext, bool AllDir)
{
    var option = AllDir ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
    return new DirectoryInfo(path).EnumerateFiles("*" + ext, option).Sum(file => file.Length);
}
public static void TEST()
{
    string folder = @"C:\Users\User\Videos";

    var bytes = GetFolderSize(folder, "mp4", true); //or GetFolderSize(folder, "mp4", false) to get all single folder only
    var totalFileSize = FormatFileSize(bytes);
    Console.WriteLine(totalFileSize);
}
0 B
857 B
173 KB
9.32 MB
1.34 MB
5.02 GB
1 B
1 KB
1 MB
1 GB
1 TB
1 PB
1 EB
public static string BytesToHumanReadable(ulong bytes)
{
    return bytes switch
    {
        (< OneKB) => $"{bytes}B",
        (>= OneKB) and (< OneMB) => $"{bytes / OneKB}KB",
        (>= OneMB) and (< OneGB) => $"{bytes / OneMB}MB",
        (>= OneGB) and (< OneTB) => $"{bytes / OneMB}GB",
        (>= OneTB) => $"{bytes / OneTB}"
        //...
    };
}