net.sf.eBus.util.HexDump Maven / Gradle / Ivy
The newest version!
//
// Copyright 2001 - 2005, 2013 Charles W. Rapp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package net.sf.eBus.util;
import java.util.Arrays;
/**
* {@link #dump(byte[], String)} generates a standard hexdump
* textual representation of binary data.
*
* @author Charles Rapp
*/
public final class HexDump
{
//---------------------------------------------------------------
// Member data.
//
//-----------------------------------------------------------
// Constants.
//
private static final int BYTES_PER_LINE = 16;
private static final int BREAK_COLUMN = 8;
private static final int SPACE_COUNT = 3;
private static final int MAX_BYTE = 256;
private static final char[] ASCII_CODE =
{
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
' ', '!', '"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.'
};
//---------------------------------------------------------------
// Member methods.
//
//-----------------------------------------------------------
// Constructors.
//
// Do not allow construction.
private HexDump()
{}
//
// end of Constructors.
//-----------------------------------------------------------
/**
* Dump out {@code data}'s entire contents starting at
* byte zero.
* @param data Generate hex dump for this data region.
* @param indent Prefix each line with this text.
* @return a text representation of the given byte array.
*/
public static String dump(final byte[] data,
final String indent)
{
return (dump(data, 0, data.length, indent));
} // end of dump(byte[], String)
/**
* Returns a text representation of the given byte array.
* The output format is:
*
*
* 0x00000000: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "........ ........"
*
*
* @param data Generate hex dump for this data region.
* @param offset Offset into the data array.
* @param size Out these many bytes in data array.
* @param indent Prefix each line with this text.
* @return a text representation of the given byte array.
*/
@SuppressWarnings({"java:S3776"})
public static String dump(final byte[] data,
final int offset,
final int size,
final String indent)
{
int address;
int lineSize;
final char[] ascii =
new char[BYTES_PER_LINE + SPACE_COUNT];
int remaining;
int index1;
int index2;
int index3;
int datum;
final StringBuilder retval = new StringBuilder();
// Continue until all the data is output.
for (index1 = 0, address = 0;
index1 < size;
index1 += lineSize, address += lineSize)
{
remaining = (size - index1);
lineSize =
(remaining < BYTES_PER_LINE ?
remaining : BYTES_PER_LINE);
// Clear out the line's text representation.
Arrays.fill(ascii, ' ');
ascii[0] = '"';
// Output the next line. Start by indenting the
// line and printing out the address.
retval.append('\n');
if (indent != null)
{
retval.append(indent);
}
retval.append(String.format("0x%08x: ", address));
// Now output the raw bytes in hex. Put three blanks
// after the eigth byte.
for (index2 = 0, index3 = 0;
index2 < lineSize;
++index2)
{
datum = data[offset + index1 + index2];
// Ignore the sign bit by adding 256 to negative
// numbers.
if (datum < 0)
{
datum += MAX_BYTE;
}
if (index2 == BREAK_COLUMN)
{
retval.append(" ");
index3 = 1;
}
else
{
retval.append(" ");
}
retval.append(String.format("%02x", datum));
// Add this byte's ASCII translation to the
// ascii array - but on if it is printable.
// Otherwise use a '.' for the byte.
ascii[index2 + index3 + 1] = ASCII_CODE[datum];
}
ascii[index2 + index3 + 1] = '"';
// Finish up this line by outputing the ascii
// representation.
// Note: if lineSize < max size, then right justify
// the ascii output.
if (lineSize < BYTES_PER_LINE)
{
for (index2 = lineSize;
index2 < BYTES_PER_LINE;
++index2)
{
if (index2 == BREAK_COLUMN)
{
retval.append(" ");
}
retval.append(" ");
}
}
retval.append(" ").append(new String(ascii));
}
return (retval.toString());
} // end of dump(byte[], String)
} // end of class HexDump