14ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/*
24ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Licensed to the Apache Software Foundation (ASF) under one or more
34ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * contributor license agreements.  See the NOTICE file distributed with
44ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * this work for additional information regarding copyright ownership.
54ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * The ASF licenses this file to You under the Apache License, Version 2.0
64ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * (the "License"); you may not use this file except in compliance with
74ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * the License.  You may obtain a copy of the License at
84ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
94ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Unless required by applicable law or agreed to in writing, software
124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * See the License for the specific language governing permissions and
154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * limitations under the License.
164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapackage org.apache.commons.io;
184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.IOException;
204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.OutputStream;
214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/**
234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Dumps data in hexadecimal format.
244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Provides a single function to take an array of bytes and display it
264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * in hexadecimal form.
274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Origin of code: POI.
294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @author Scott Sanders
314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @author Marc Johnson
324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @version $Id: HexDump.java 596667 2007-11-20 13:50:14Z niallp $
334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapublic class HexDump {
354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Instances should NOT be constructed in standard programming.
384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public HexDump() {
404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        super();
414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Dump an array of bytes to an OutputStream.
454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param data  the byte array to be dumped
474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param offset  its offset, whatever that might mean
484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param stream  the OutputStream to which the data is to be
494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *               written
504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param index initial index into the byte array
514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException is thrown if anything goes wrong writing
534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *         the data to stream
544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws ArrayIndexOutOfBoundsException if the index is
554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *         outside the data array's bounds
564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IllegalArgumentException if the output stream is null
574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public static void dump(byte[] data, long offset,
604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                            OutputStream stream, int index)
614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throws IOException, ArrayIndexOutOfBoundsException,
624ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            IllegalArgumentException {
634ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
644ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if ((index < 0) || (index >= data.length)) {
654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new ArrayIndexOutOfBoundsException(
664ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    "illegal index: " + index + " into array of length "
674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    + data.length);
684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (stream == null) {
704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IllegalArgumentException("cannot write to nullstream");
714ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
724ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        long display_offset = offset + index;
734ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        StringBuffer buffer = new StringBuffer(74);
744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
754ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        for (int j = index; j < data.length; j += 16) {
764ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            int chars_read = data.length - j;
774ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
784ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            if (chars_read > 16) {
794ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                chars_read = 16;
804ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            }
814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            dump(buffer, display_offset).append(' ');
824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            for (int k = 0; k < 16; k++) {
834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                if (k < chars_read) {
844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    dump(buffer, data[k + j]);
854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                } else {
864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    buffer.append("  ");
874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                }
884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                buffer.append(' ');
894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            }
904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            for (int k = 0; k < chars_read; k++) {
914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                if ((data[k + j] >= ' ') && (data[k + j] < 127)) {
924ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    buffer.append((char) data[k + j]);
934ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                } else {
944ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    buffer.append('.');
954ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                }
964ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            }
974ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            buffer.append(EOL);
984ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            stream.write(buffer.toString().getBytes());
994ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            stream.flush();
1004ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            buffer.setLength(0);
1014ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            display_offset += chars_read;
1024ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1034ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1044ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1054ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1064ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * The line-separator (initializes to "line.separator" system property.
1074ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1084ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public static final String EOL =
1094ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            System.getProperty("line.separator");
1104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private static final char[] _hexcodes =
1114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            {
1124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                'A', 'B', 'C', 'D', 'E', 'F'
1144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            };
1154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private static final int[] _shifts =
1164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            {
1174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                28, 24, 20, 16, 12, 8, 4, 0
1184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            };
1194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Dump a long value into a StringBuffer.
1224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param _lbuffer the StringBuffer to dump the value in
1244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param value  the long value to be dumped
1254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return StringBuffer containing the dumped value.
1264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private static StringBuffer dump(StringBuffer _lbuffer, long value) {
1284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        for (int j = 0; j < 8; j++) {
1294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            _lbuffer
1304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    .append(_hexcodes[((int) (value >> _shifts[j])) & 15]);
1314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return _lbuffer;
1334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Dump a byte value into a StringBuffer.
1374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param _cbuffer the StringBuffer to dump the value in
1394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param value  the byte value to be dumped
1404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return StringBuffer containing the dumped value.
1414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private static StringBuffer dump(StringBuffer _cbuffer, byte value) {
1434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        for (int j = 0; j < 2; j++) {
1444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            _cbuffer.append(_hexcodes[(value >> _shifts[j + 6]) & 15]);
1454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return _cbuffer;
1474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira}
150