Does .NET provide an easy way convert bytes to KB,

2019-01-04 19:01发布

Just wondering if .NET provides a clean way to do this:

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

etc...

19条回答
Melony?
2楼-- · 2019-01-04 19:27

Here is an option that's easier to extend than yours, but no, there is none built into the library itself.

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();
}
查看更多
【Aperson】
3楼-- · 2019-01-04 19:27
    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;
        }
    }

This is one way to do it aswell (The number 1073741824.0 is from 1024*1024*1024 aka GB)

查看更多
家丑人穷心不美
4楼-- · 2019-01-04 19:30

I went for JerKimballs solution, and thumbs up to that. However, I would like to add / point out that this is indeed a matter of controversy as a whole. In my research (for other reasons) I have come up with the following pieces of information.

When normal people (I have heard they exist) speak of gigabytes they refer to the metric system wherein 1000 to the power of 3 from the original number of bytes == the number of gigabytes. However, of course there is the IEC / JEDEC standards which is nicely summed up in wikipedia, which instead of 1000 to the power of x they have 1024. Which for physical storage devices (and I guess logical such as amazon and others) means an ever increasing difference between metric vs IEC. So for instance 1 TB == 1 terabyte metric is 1000 to the power of 4, but IEC officially terms the similar number as 1 TiB, tebibyte as 1024 to the power of 4. But, alas, in non-technical applications (I would go by audience) the norm is metric, and in my own app for internal use currently I explain the difference in documentation. But for display purposes I do not even offer anything but metric. Internally even though it's not relevant in my app I only store bytes and do the calculation for display.

As a side note I find it somewhat lackluster that the .Net framework AFAIK (and I am frequently wrong thank the powers that be) even in it's 4.5 incarnation does not contain anything about this in any libraries internally. One would expect an open source library of some kind to be NuGettable at some point, but I admit this is a small peeve. On the other hand System.IO.DriveInfo and others also only have bytes (as long) which is rather clear.

查看更多
Bombasti
5楼-- · 2019-01-04 19:36

No. Mostly because it's of a rather niche need, and there are too many possible variations. (Is it "KB", "Kb" or "Ko"? Is a megabyte 1024 * 1024 bytes, or 1024 * 1000 bytes? -- yes, some places use that!)

查看更多
该账号已被封号
6楼-- · 2019-01-04 19:36

As posted above, the recursion is the favorite way, with the help of logarithm.

The following function has 3 arguments : the input, the dimension constraint of the output, that is the third argument.

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

Now let's convert 12GB of RAM in several units:

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
}
查看更多
Rolldiameter
7楼-- · 2019-01-04 19:37

How about some recursion:

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

Then you can call it:

ReturnSize(size, string.Empty);
查看更多
登录 后发表回答