View Javadoc
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 }