in ch-commons-util/src/main/java/com/cloudhopper/commons/util/StringUtil.java [585:657]
public static String hexDump(String prefix, byte[] data) {
byte byte_value;
StringBuffer str = new StringBuffer(data.length * 3);
str.append(prefix);
for (int i = 0; i < data.length; i += 16) {
// dump the header: 00000000:
String offset = Integer.toHexString(i);
// "0" left pad offset field so it is always 8 char's long.
str.append(" ");
for (int offlen = offset.length(); offlen < 8; offlen++) {
str.append("0");
}
str.append(offset);
str.append(":");
// dump hex version of 16 bytes per line.
for (int j = 0; (j < 16) && ((i + j) < data.length); j++) {
byte_value = data[i + j];
// add spaces between every 2 bytes.
if ((j % 2) == 0) {
str.append(" ");
}
// dump a single byte.
byte high_nibble = (byte) ((byte_value & 0xf0) >>> 4);
byte low_nibble = (byte) (byte_value & 0x0f);
str.append(HEX_TABLE[high_nibble]);
str.append(HEX_TABLE[low_nibble]);
}
// IF THIS IS THE LAST LINE OF HEX, THEN ADD THIS
if (i + 16 > data.length) {
// for debugging purposes, I want the last bytes always padded
// over so that the ascii portion is correctly positioned
int last_row_byte_count = data.length % 16;
int num_bytes_short = 16 - last_row_byte_count;
// number of spaces to add = (num bytes remaining * 2 spaces per byte) + (7 - (num bytes % 2))
int num_spaces = (num_bytes_short * 2) + (7 - (last_row_byte_count / 2));
for (int v = 0; v < num_spaces; v++) {
str.append(" ");
}
}
// dump ascii version of 16 bytes
str.append(" ");
for (int j = 0; (j < 16) && ((i + j) < data.length); j++) {
char char_value = (char) data[i + j];
// RESOLVE (really want isAscii() or isPrintable())
//if (Character.isLetterOrDigit(char_value))
if (isPrintableChar(char_value)) {
str.append(String.valueOf(char_value));
} else {
str.append(".");
}
}
// new line
str.append("\n");
}
// always trim off the last newline
str.deleteCharAt(str.length() - 1);
return (str.toString());
}