import java.io.*;


/**
 * Generates a hex representation of an given file.
 *
 * @author  Michael Meyling
 */
public class Hex {

    public static void main(String[] args) {

        try {
            if (args.length <= 0) {
                System.out.println("Hex <filename>");
                return;
            }
            for (int i = 0; i < args.length; i++) {
                final File f = new File(args[i]);
                final int size = (int) f.length();
                final BufferedInputStream in 
                    = new BufferedInputStream(new FileInputStream(f));
                final byte[] data = new byte[size];
                int bytesread = 0;
                while (bytesread < size) {
                    bytesread += in.read(data, bytesread, size - bytesread);
                }
                in.close();
                BufferedWriter out = new BufferedWriter(
                    new FileWriter(args[i] + ".hex"));
                out.write(toHex(data));
                out.close();
                final byte[] compare = toBin(toHex(data));
                if (compare.length != data.length) {
                    throw new IllegalArgumentException("different length");
                }
                for (int j = 0; j < data.length; j++) {
                    if (data[j] != compare[j]) {
                        throw new IllegalArgumentException("difference in char " + j);
                    }
                }

            }

            System.out.println("..done");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("..failed");
        }

    }   


    /**
     * Get a hex string representation for an byte array.
     * 
     * @param   data    <code>byte</code> array to work on
     * @return  hex string of <code>data</code>
     */
    private static String toHex(byte [] data) {

        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            String b = Integer.toHexString(255 & data[i]);
            if (i != 0) {
                if (0 != i % 16) {
                    buffer.append(" ");
                } else {
                    buffer.append("\n");
                }
            }
            if (b.length() < 2) {
                buffer.append("0");
            }
            buffer.append(b.toUpperCase());
        }
        return buffer.toString();
    }


    /**
     * Get a byte array out of a hex string representation.
     * 
     * @param   hex    hex string representation of data
     * @return  data bytes
     */
    private static byte[] toBin(String hex) {

        StringBuffer buffer = new StringBuffer(hex.length());
        char c;
        for (int i = 0; i < hex.length(); i++) {
            if (!Character.isWhitespace(c = hex.charAt(i))) {
                if (!Character.isLetterOrDigit(c)) {
                    throw new IllegalArgumentException("Illegal hex char");
                }
                buffer.append(c);
            }
        }
        if (buffer.length() % 2 != 0) {
            throw new IllegalArgumentException("Bad padding");
        }
        byte[] result = new byte[buffer.length() / 2];
        for (int i = 0; i < result.length; i++) {
            try {
                result[i] = (byte)Integer.parseInt(buffer.substring(2*i, 2*i + 2), 16);
            } catch (Exception e) {
                throw new IllegalArgumentException("Illegal hex char");
            }
        }
        return result;
    }





}
