1 package com.ericsson.research.trap.utils;
2
3 /*
4 * ##_BEGIN_LICENSE_##
5 * Transport Abstraction Package (trap)
6 * ----------
7 * Copyright (C) 2014 Ericsson AB
8 * ----------
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice, this
13 * list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Ericsson AB nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32 * OF THE POSSIBILITY OF SUCH DAMAGE.
33 * ##_END_LICENSE_##
34 */
35
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 import java.io.PrintStream;
39 import java.io.UnsupportedEncodingException;
40
41 /**
42 * Utility class to print out hexadecimal and pretty data, primarily for debug purposes. When printed, the data is shown
43 * in a reasonable and understandable format, like the one below.
44 *
45 * <pre>
46 * 54 68 69 73 20 69 73 20 61 6e 20 65 78 61 6d 70 6c 65 20 6f This.is.an.example.o
47 * 66 20 68 65 78 20 64 75 6d 70 69 6e 67 20 73 6f 6d 65 20 62 f.hex.dumping.some.b
48 * 79 74 65 73 2e 2e 2e ytes...
49 * </pre>
50 *
51 * @author Vladimir Katardjiev
52 * @since 1.1
53 */
54 public class HexDump
55 {
56
57 /**
58 * @hide
59 * @param args
60 * @throws IOException
61 */
62 public static void main(String[] args) throws IOException
63 {
64 byte[] bytes = StringUtil.toUtfBytes("This is an example of hex dumping some bytes...");//read(inputFileName, start, end);
65 for (int index = 0; index < bytes.length; index += 20)
66 {
67 printHex(bytes, index, 20, System.out);
68 printAscii(bytes, index, 20, System.out);
69 }
70 }
71
72 /**
73 * Creates a new object with a toString method that will lazily perform a HexDump on the supplied data. This can be
74 * used when it is not known if the resulting string will be printed, to save on some computation.
75 *
76 * @param bytes
77 * The bytes to HexDump
78 * @param start
79 * Offset in the bytes to start at.
80 * @param width
81 * Width (in bytes) of the hex dump
82 * @return An object with a toString() method that returns the hexDump.
83 */
84 public static Object makeStringifyable(final byte[] bytes, final int start, final int width)
85 {
86 return new Object() {
87
88 String str = null;
89
90 public String toString()
91 {
92 if (this.str == null)
93 {
94 ByteArrayOutputStream bos = new ByteArrayOutputStream();
95 PrintStream ps;
96 try
97 {
98 ps = new PrintStream(bos, true, "UTF-8");
99 printBytes(bytes, start, width, ps);
100 this.str = bos.toString("UTF-8");
101 }
102 catch (UnsupportedEncodingException e)
103 {
104 e.printStackTrace();
105 this.str = "Unsupported Encoding";
106 }
107 }
108 return this.str;
109 }
110
111 };
112 }
113
114 /**
115 * Prints the supplied bytes as ASCII to System.out.
116 *
117 * @param bytes
118 * The bytes to print
119 * @param start
120 * Index to start printing from
121 * @param width
122 * Width in bytes
123 * @see #printBytes(byte[], int, int, PrintStream)
124 */
125 public static void printBytes(byte[] bytes, int start, int width)
126 {
127 printBytes(bytes, start, width, System.out);
128 }
129
130 /**
131 * Prints a set of bytes to a given stream. The output format is the one specified in the class description. Prints
132 * the bytes as hex and ascii until the end of the byte array.
133 *
134 * @param bytes
135 * The source bytes to print.
136 * @param start
137 * The offset to start printing from.
138 * @param width
139 * Width in bytes of the printed output
140 * @param ps
141 * The stream to print to.
142 */
143 public static void printBytes(byte[] bytes, int start, int width, PrintStream ps)
144 {
145 for (int index = 0; index < bytes.length; index += width)
146 {
147 printHex(bytes, index, width, ps);
148 try
149 {
150 printAscii(bytes, index, width, ps);
151 }
152 catch (UnsupportedEncodingException e)
153 {
154 }
155 }
156 }
157
158 private static void printHex(byte[] bytes, int offset, int width, PrintStream os)
159 {
160 for (int index = 0; index < width; index++)
161 {
162 if (index + offset < bytes.length)
163 {
164 os.printf("%02x ", bytes[index + offset]);
165 }
166 else
167 {
168 os.print(" ");
169 }
170 }
171 }
172
173 private static void printAscii(byte[] bytes, int index, int width, PrintStream ps) throws UnsupportedEncodingException
174 {
175 if (index < bytes.length)
176 {
177 width = Math.min(width, bytes.length - index);
178 ps.println(new String(bytes, index, width, "US-ASCII").replaceAll("[^\\x21-\\x7E]", "."));
179 }
180 else
181 {
182 ps.println();
183 }
184 }
185
186 private HexDump(){}
187 }