package ua.stu.scplib.tools; /** * <p>Various static methods helpful for dumping decimal and hexadecimal values.</p> * * @author dclunie */ public class HexDump { private HexDump() {} /** * <p>Convert an integer value to a decimal string, padding it to a specified length, and prepending a prefix and appending a suffix.</p> * * @param i the integer to dump * @param pad the pad character to append before the string value of the integer if necessary * @param length the desired length of string converted integer and padding (not including the prefix or suffix) * @param prefix the string to prepend * @param suffix the string to append * @return the prefix, padded decimal string and suffix */ public static String toPaddedDecimalString(int i,char pad,int length,String prefix,String suffix) { StringBuffer sb = new StringBuffer(); if (prefix != null) sb.append(prefix); String s=Integer.toString(i); // decimal string int ls=s.length(); while(ls++ < length) { sb.append(pad); } sb.append(s); // even if it is longer than length wanted if (suffix != null) sb.append(suffix); return sb.toString(); } /** * <p>Convert an unsigned byte value to a decimal string of three characters with leading space padding.</p> * * @param i the unsigned byte value * @return the padded decimal string */ public static String byteToPaddedDecimalString(int i) { return toPaddedDecimalString(i&0xff,' ',3,null,null); } /** * <p>Convert an unsigned short value to a decimal string of six characters with leading space padding.</p> * * @param i the unsigned short value * @return the padded decimal string */ public static String shortToPaddedDecimalString(int i) { return toPaddedDecimalString(i&0xffff,' ',6,null,null); } /** * <p>Convert an integer value to a decimal string of nine characters with leading space padding.</p> * * @param i the integer value * @return the padded decimal string */ public static String intToPaddedDecimalString(int i) { return toPaddedDecimalString(i&0xffffffff,' ',9,null,null); } /** * <p>Convert an integer value to a hexadecimal string, padding it to a specified length, and prepending a prefix and appending a suffix.</p> * * @param i the integer to dump * @param pad the pad character to append before the string value of the integer if necessary * @param length the desired length of string converted integer and padding (not including the prefix or suffix) * @param prefix the string to prepend * @param suffix the string to append * @return the prefix, padded hexadecimal string and suffix */ public static String toPaddedHexString(int i,char pad,int length,String prefix,String suffix) { StringBuffer sb = new StringBuffer(); if (prefix != null) sb.append(prefix); String s=Integer.toHexString(i); int ls=s.length(); while(ls++ < length) { sb.append(pad); } sb.append(s); // even if it is longer than length wanted if (suffix != null) sb.append(suffix); return sb.toString(); } /** * <p>Convert an unsigned byte value to a hexadecimal string of two characters with leading zero padding.</p> * * @param i the unsigned byte value * @return the padded hexadecimal string */ public static String byteToPaddedHexString(int i) { return toPaddedHexString(i&0xff,'0',2,null,null); } /** * <p>Convert an unsigned short value to a hexadecimal string of four characters with leading zero padding.</p> * * @param i the unsigned short value * @return the padded decimal string */ public static String shortToPaddedHexString(int i) { return toPaddedHexString(i&0xffff,'0',4,null,null); } /** * <p>Convert an integer value to a hexadecimal string of eight characters with leading zero padding.</p> * * @param i the integer value * @return the padded decimal string */ public static String intToPaddedHexString(int i) { return toPaddedHexString(i&0xffffffff,'0',8,null,null); } /** * <p>Convert an unsigned byte value to a hexadecimal string of two characters with leading 0x and leading zero padding.</p> * * @param i the unsigned byte value * @return the padded hexadecimal string */ public static String byteToPaddedHexStringWith0x(int i) { return toPaddedHexString(i&0xff,'0',2,"0x",null); } /** * <p>Convert an unsigned short value to a hexadecimal string of four characters with leading 0x and leading zero padding.</p> * * @param i the unsigned short value * @return the padded decimal string */ public static String shortToPaddedHexStringWith0x(int i) { return toPaddedHexString(i&0xffff,'0',4,"0x",null); } /** * <p>Convert an integer value to a hexadecimal string of eight characters with leading 0x and leading zero padding.</p> * * @param i the integer value * @return the padded decimal string */ public static String intToPaddedHexStringWith0x(int i) { return toPaddedHexString(i&0xffffffff,'0',8,"0x",null); } /** * <p>Test whether or not a character in the default character set is printable.</p> * * @param c character to test * @return true if character is printable */ public static boolean isPrintableCharacter(char c) { // as it happens, for ASCII at least, the only characters // between 0 and 127 that are not in this list have a // type of Character.CONTROL // still, just in case ... switch (Character.getType(c)) { case Character.LOWERCASE_LETTER: case Character.UPPERCASE_LETTER: case Character.DECIMAL_DIGIT_NUMBER: case Character.SPACE_SEPARATOR: case Character.CONNECTOR_PUNCTUATION: case Character.DASH_PUNCTUATION: case Character.START_PUNCTUATION: case Character.END_PUNCTUATION: //case Character.INITIAL_QUOTE_PUNCTUATION: //case Character.FINAL_QUOTE_PUNCTUATION: case Character.OTHER_PUNCTUATION: case Character.MATH_SYMBOL: case Character.CURRENCY_SYMBOL: case Character.MODIFIER_SYMBOL: case Character.OTHER_SYMBOL: case Character.OTHER_LETTER: case Character.TITLECASE_LETTER: case Character.NON_SPACING_MARK: case Character.COMBINING_SPACING_MARK: case Character.ENCLOSING_MARK: return true; default: return false; } } /** * <p>Create a printable string representation of a specified portion of a byte array in the default character set.</p> * * <p>Unprintable characters are represented by a period ('.') character.</p> * * @param b the byte array * @param offset the start of the bytes to be extracted * @param length the number of bytes to be extracted * @return a string of the specified length containing the printable characters of the supplied bytes */ public static String byteArrayToPrintableString(byte[] b,int offset,int length) { StringBuffer sb = new StringBuffer(); sb.append(" "); while (length-- > 0) { char c = (char)b[offset++]; if (isPrintableCharacter(c)) sb.append(c); else //sb.append("**"+Character.getType(c)+"**"); sb.append("."); //sb.append(" "); } return sb.toString(); } /** * <p>Create a dump of the decimal offset, hexadecimal values and printable string values of a byte array.</p> * * <p>The result is similar to a dump produced by the unix od or MacOS X 'hexdump -C' commands.</p> * * @param b the byte array to be dumped * @param offset the offset into the buffer to be dumped * @param lng the number of bytes to be dumped * @return a string containing the multiline result */ public static String dump(byte[] b,int offset,int lng) { StringBuffer sb = new StringBuffer(); if (b != null && lng > 0) { int i=0; int stringStart=0; int stringCount=0; while (i < lng) { int position = i+offset; if (i%16 == 0) { if (i != 0) sb.append("\n"); sb.append(intToPaddedDecimalString(position)); sb.append(" ("); sb.append(intToPaddedHexStringWith0x(position)); sb.append("):"); stringStart=position; stringCount=0; } sb.append(" "); sb.append(byteToPaddedHexString(b[position])); ++i; ++stringCount; if (i%16 == 0 || i == lng) sb.append(byteArrayToPrintableString(b,stringStart,stringCount)); } } sb.append("\n"); return sb.toString(); } /** * <p>Create a dump of the decimal offset, hexadecimal values and printable string values of a byte array.</p> * * <p>The result is similar to a dump produced by the unix od or MacOS X 'hexdump -C' commands.</p> * * @param b the byte array to be dumped * @param lng the number of bytes to be dumped * @return a string containing the multiline result */ public static String dump(byte[] b,int lng) { return dump(b,0,lng); } /** * <p>Create a dump of the decimal offset, hexadecimal values and printable string values of a byte array.</p> * * <p>The result is similar to a dump produced by the unix od or MacOS X 'hexdump -C' commands.</p> * * @param b the byte array to be dumped in its entirety * @return a string containing the multiline result */ public static String dump(byte[] b) { return dump(b, b == null ? 0 : b.length); } /** * <p>Create a dump of the decimal offset, hexadecimal values of the Unicode code points and printable string values of a String.</p> * * @param s the String to be dumped * @param offset the offset into the String to be dumped * @param lng the number of characters to be dumped * @return a string containing the multiline result */ public static String dump(String s,int offset,int lng) { StringBuffer sb = new StringBuffer(); if (s != null && lng > 0) { int i=0; int stringStart=0; int stringCount=0; while (i < lng) { int position = i+offset; if (i%8 == 0) { if (i != 0) sb.append("\n"); sb.append(intToPaddedDecimalString(position)); sb.append(" ("); sb.append(intToPaddedHexStringWith0x(position)); sb.append("):"); stringStart=position; stringCount=0; } sb.append(" "); sb.append(intToPaddedHexString(Character.codePointAt(s,position))); ++i; ++stringCount; if (i%8 == 0 || i == lng) { sb.append(" "); sb.append(s.substring(stringStart,stringStart+stringCount-1)); } } } sb.append("\n"); return sb.toString(); } /** * <p>Create a dump of the decimal offset, hexadecimal values of the Unicode code points and printable string values of a String.</p> * * @param s the String to be dumped * @param lng the number of characters to be dumped * @return a string containing the multiline result */ public static String dump(String s,int lng) { return dump(s,0,lng); } /** * <p>Create a dump of the decimal offset, hexadecimal values of the Unicode code points and printable string values of a String.</p> * * @param s the String to be dumped dumped in its entirety * @return a string containing the multiline result */ public static String dump(String s) { return dump(s, s == null ? 0 : s.length()); } /** * <p>Unit test.</p> * * @param arg ignored */ public static void main(String arg[]) { byte[] b = new byte[256]; for (int i=0; i<256; ++i) b[i]=(byte)i; System.err.println(dump(b)); } }