It’s one of those simple UI things that make a real difference. You have to be pretty special to be able to instantly convert 45742364 bytes into 43.6MB in your head.

Enter some great code snippets I’ve discovered on StackOverflow that do this. This four line wonder is top answer to that question (from Mr Ed.):

1 2 3 4 5 6 |
public static String readableFileSize(long size) { if(size <= 0) return "0"; final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; int digitGroups = (int) (Math.log10(size)/Math.log10(1024)); return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + " " + units[digitGroups]; } |

There’s another similar answer to this question, that can also produces binary units (from aioobe):

1 2 3 4 5 6 7 |
public static String humanReadableByteCount(long bytes, boolean si) { int unit = si ? 1000 : 1024; if (bytes < unit) return bytes + " B"; int exp = (int) (Math.log(bytes) / Math.log(unit)); String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); } |

Unfortunately, neither of these will work on the client side of GWT. String.format and DecimalFormat all give it a Sadface.

### How do we make it work with GWT?

We drop in the excellent GWT NumberFormat. With very little effort we end up with this fully GWT compatible version:

1 2 3 4 5 6 |
public static String readableFileSize(long size) { if(size <= 0) return "0"; final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; int digitGroups = (int) (Math.log10(size)/Math.log10(1024)); return NumberFormat.getFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + " " + units[digitGroups]; } |

Which is lovely. Happyface once more.