Menu

Byte-Size formatter for your Byte-Size Needs

December 5, 2012 - .NET, C#

Formatting Data Sizes

When we present file-based data to a user, it is often unavoidable to show those byte sizes to the user. While you could get away with a formatted display of the number of bytes, for large files, this loses quite a bit of meaning. Instead, the ideal would be to format it to a prefix, selected based on the actual size.

In order to implement this functionality, let’s create a “ByteSizeFormatter” class. We’ll make it static, and add some string arrays for both the standard as well as the ISO suffixes:

Why use an array? Well, now we can get the appropriate element to use from a given byte size with a bit of math:

And students complain that they’ll never use logarithms in real life. If they became programmers they probably would have implemented the above like this:

TSSK! I say to that. Anyway, the idea here is to get the index of the prefix that, when applied, will give a number above zero but less than 1024; obviously, the idea is to use this routine within another:

[code]
public static String FormatSize(long amount,int numdecimalplaces=2,bool useISO=false)
{
String[] usesuffixes = useISO ? isobytesuffixes : stdbytesuffixes;
int gotindex = getbyteprefixindex(amount);
double calcamount = amount;
calcamount = calcamount / (Math.Pow(1024, gotindex));
return calcamount.ToString(“F” + numdecimalplaces.ToString(CultureInfo.InvariantCulture),
CultureInfo.CurrentCulture) + ” ” + usesuffixes[gotindex];

}
[/code]

FormatSize() formats a given byte amount into an “optimal” value with an appropriate prefix. It does this by generating the appropriate format string to pass to the ToString() method based on the passed number of decimal places.

What else?

So we have a method for formatting a single size. However, we might want to format several sizes with the same “format”; that is, we might want to format a set of values but have them all “comparable” to each other at a glance; 512K can look larger than 3MB at a quick glance, and it is a lot easier to judge and compare file sizes when the values are something you can compare. The first step is a helper method that accepts a calculated index:

“But WAAAIT!” I here you screaming- “That’s duplicating code!” Of course it is- that’s why we can replace the FormatSize() method with a delegated call to this one, like so:

Then, we can use that to create the imagined method from before:

Tada! The capability of Linq is very helpful here since it helps us make the code only three statements, whereas it might normally take more for various loops. This particular implementation is also an enumerator method, simply because it doesn’t strictly require anything specific to arrays.

To finish off- the full source of this class as it appears in my BASeCamp.Updating library:

Have something to say about this post? Comment!