/* * HumanBytes.java * Copyright (C) 2006 Nicholas Killewald * * This file is distributed under the terms of the BSD license. * See the LICENSE file under the toplevel images/ directory for terms. */ package net.exclaimindustries.tools; import java.text.NumberFormat; /** *<p> * <CODE>HumanBytes</CODE> contains a set of static methods that help in making * lengths of bytes easier to read by humans. As in, it attaches 'k' and 'M' * suffixes where appropriate and truncates values. Note that these represent * kilobytes in multiples of 1024, not 1000, and likewise up the chain. *</p> * *<p> * Something tells me something in Java does this already, but I was having fun * one day and just decided to code this up. *</p> * * @author Nicholas Killewald */ public final class HumanBytes { /** One kilobye (1024) */ public static final long ONEKILO = 1024; /** One megabyte (1024^2) */ public static final long ONEMEG = 1048576; /** One gigabyte (1024^3) */ public static final long ONEGIG = 1073741824; /** One terabyte (1024^4) */ public static final long ONETERA = 1099511627776L; /** One petabyte (1024^5) */ public static final long ONEPETA = 1125899906842624L; /** *<p> * Turns the specified long into whatever the most ideal qualifier is. That * is, reduce it to whatever makes the most sense. For some examples: *</p> * *<ul> *<li><code>HumanBytes.toIdeal(54099l)</code> returns "54.83kB" *<li><code>HumanBytes.toIdeal(84312267l)</code> returns "80.41MB" *<li><code>HumanBytes.toIdeal(463311975466l)</code> returns "431.5GB" *</ul> * *<p> * Thus, this simply calls other methods depending on the size of the long. * Note that this will account for negatives if need be. *</p> * * @param input * long to convert * @return a String of the ideal human-readable representation of the long */ public static String toIdeal(long input) { // NOTE TO SELF: A long is a 64-bit signed value. 64 bits of value // is 18,446,744,073,709,551,616. So, 64 bits of signed value would // be in the 9e18 range. (base), k, M, G, T, P. // First off, if this is less than 1024 (by absoluteness), just return // it. if (Math.abs(input) < 1024) return input + "B"; // Now, go in order from biggest to smallest. Comparisons are easier // on the system than comparisons and divisions. if (Math.abs(input) >= ONEPETA) return toPeta(input); if (Math.abs(input) >= ONETERA) return toTera(input); if (Math.abs(input) >= ONEGIG) return toGiga(input); if (Math.abs(input) >= ONEMEG) return toMega(input); if (Math.abs(input) >= ONEKILO) return toKilo(input); // Fall out; this can't happen return input + "B"; } /** * Turns the given long into a petabyte representation. * * @param input * long to convert * @return String representation of the input in petabytes */ public static String toPeta(long input) { float toReturn = (float)(input) / ONEPETA; return finishIt(toReturn, "PB"); } /** * Turns the given long into a terabyte representation. * * @param input * long to convert * @return String representation of the input in terabytes */ public static String toTera(long input) { float toReturn = (float)(input) / ONETERA; return finishIt(toReturn, "TB"); } /** * Turns the given long into a gigabyte representation. * * @param input * long to convert * @return String representation of the input in gigabytes */ public static String toGiga(long input) { float toReturn = (float)(input) / ONEGIG; return finishIt(toReturn, "GB"); } /** * Turns the given long into a megabyte representation. * * @param input * long to convert * @return String representation of the input in megabytes */ public static String toMega(long input) { float toReturn = (float)(input) / ONEMEG; return finishIt(toReturn, "MB"); } /** * Turns the given long into a kilobyte representation. * * @param input * long to convert * @return String representation of the input in kilobytes */ public static String toKilo(long input) { float toReturn = (float)(input) / ONEKILO; return finishIt(toReturn, "kB"); } /** *<p> * Finishes up output from a conversion. This means putting the right * decimals in, adding commas, and attaching the suffix. *</p> * * @param input * number to convert * @param suffix * suffix to attach to the result * @return the appropriately formatted number */ private static String finishIt(float input, String suffix) { NumberFormat nf = NumberFormat.getInstance(); // If the resulting number is >= 1,000, just return // the int part of it and appropriate commas. if (Math.abs(input) >= 1000) { nf.setMaximumFractionDigits(0); return nf.format(input) + suffix; } // In the range of 100 to 999, we want one decimal if (Math.abs(input) < 1000 && Math.abs(input) >= 100) { nf.setMaximumFractionDigits(1); return nf.format(input) + suffix; } // In the range of 0 to 99, we want two decimals if (Math.abs(input) < 100 && Math.abs(input) >= 0) { nf.setMaximumFractionDigits(2); return nf.format(input) + suffix; } // And now we just kinda die. return nf.format(input) + suffix; } }