1 2 /* ==================================================================== 3 * The Apache Software License, Version 1.1 4 * 5 * Copyright (c) 2002 The Apache Software Foundation. All rights 6 * reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The end-user documentation included with the redistribution, 21 * if any, must include the following acknowledgment: 22 * "This product includes software developed by the 23 * Apache Software Foundation (http://www.apache.org/)." 24 * Alternately, this acknowledgment may appear in the software itself, 25 * if and wherever such third-party acknowledgments normally appear. 26 * 27 * 4. The names "Apache" and "Apache Software Foundation" and 28 * "Apache POI" must not be used to endorse or promote products 29 * derived from this software without prior written permission. For 30 * written permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * "Apache POI", nor may "Apache" appear in their name, without 34 * prior written permission of the Apache Software Foundation. 35 * 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This software consists of voluntary contributions made by many 51 * individuals on behalf of the Apache Software Foundation. For more 52 * information on the Apache Software Foundation, please see 53 * <http://www.apache.org/>. 54 */ 55 56 package org.apache.poi.util; 57 58 import java.io.*; 59 60 /** 61 * dump data in hexadecimal format; derived from a HexDump utility I 62 * wrote in June 2001. 63 * 64 * @author Marc Johnson 65 * @author Glen Stampoultzis (glens at apache.org) 66 */ 67 68 public class HexDump 69 { 70 71 // all static methods, so no need for a public constructor 72 private HexDump() 73 { 74 } 75 76 /** 77 * dump an array of bytes to an OutputStream 78 * 79 * @param data the byte array to be dumped 80 * @param offset its offset, whatever that might mean 81 * @param stream the OutputStream to which the data is to be 82 * written 83 * @param index initial index into the byte array 84 * @param length number of characters to output 85 * 86 * @exception IOException is thrown if anything goes wrong writing 87 * the data to stream 88 * @exception ArrayIndexOutOfBoundsException if the index is 89 * outside the data array's bounds 90 * @exception IllegalArgumentException if the output stream is 91 * null 92 */ 93 public synchronized static void dump(final byte [] data, final long offset, 94 final OutputStream stream, final int index, final int length) 95 throws IOException, ArrayIndexOutOfBoundsException, 96 IllegalArgumentException 97 { 98 if ((index < 0) || (index >= data.length)) 99 { 100 throw new ArrayIndexOutOfBoundsException( 101 "illegal index: " + index + " into array of length " 102 + data.length); 103 } 104 if (stream == null) 105 { 106 throw new IllegalArgumentException("cannot write to nullstream"); 107 } 108 long display_offset = offset + index; 109 StringBuffer buffer = new StringBuffer(74); 110 111 112 int data_length = Math.min(data.length,index+length); 113 for (int j = index; j < data_length; j += 16) 114 { 115 int chars_read = data_length - j; 116 117 if (chars_read > 16) 118 { 119 chars_read = 16; 120 } 121 buffer.append( 122 dump(display_offset) 123 ).append(' '); 124 for (int k = 0; k < 16; k++) 125 { 126 if (k < chars_read) 127 { 128 buffer.append(dump(data[ k + j ])); 129 } 130 else 131 { 132 buffer.append(" "); 133 } 134 buffer.append(' '); 135 } 136 for (int k = 0; k < chars_read; k++) 137 { 138 if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127)) 139 { 140 buffer.append(( char ) data[ k + j ]); 141 } 142 else 143 { 144 buffer.append('.'); 145 } 146 } 147 buffer.append(EOL); 148 stream.write(buffer.toString().getBytes()); 149 stream.flush(); 150 buffer.setLength(0); 151 display_offset += chars_read; 152 } 153 154 } 155 156 /** 157 * dump an array of bytes to an OutputStream 158 * 159 * @param data the byte array to be dumped 160 * @param offset its offset, whatever that might mean 161 * @param stream the OutputStream to which the data is to be 162 * written 163 * @param index initial index into the byte array 164 * 165 * @exception IOException is thrown if anything goes wrong writing 166 * the data to stream 167 * @exception ArrayIndexOutOfBoundsException if the index is 168 * outside the data array's bounds 169 * @exception IllegalArgumentException if the output stream is 170 * null 171 */ 172 173 public synchronized static void dump(final byte [] data, final long offset, 174 final OutputStream stream, final int index) 175 throws IOException, ArrayIndexOutOfBoundsException, 176 IllegalArgumentException 177 { 178 dump(data, offset, stream, index, data.length-index); 179 } 180 181 /** 182 * dump an array of bytes to a String 183 * 184 * @param data the byte array to be dumped 185 * @param offset its offset, whatever that might mean 186 * @param index initial index into the byte array 187 * 188 * @exception ArrayIndexOutOfBoundsException if the index is 189 * outside the data array's bounds 190 * @return output string 191 */ 192 193 public static String dump(final byte [] data, final long offset, 194 final int index) { 195 StringBuffer buffer; 196 if ((index < 0) || (index >= data.length)) 197 { 198 throw new ArrayIndexOutOfBoundsException( 199 "illegal index: " + index + " into array of length " 200 + data.length); 201 } 202 long display_offset = offset + index; 203 buffer = new StringBuffer(74); 204 205 for (int j = index; j < data.length; j += 16) 206 { 207 int chars_read = data.length - j; 208 209 if (chars_read > 16) 210 { 211 chars_read = 16; 212 } 213 buffer.append(dump(display_offset)).append(' '); 214 for (int k = 0; k < 16; k++) 215 { 216 if (k < chars_read) 217 { 218 buffer.append(dump(data[ k + j ])); 219 } 220 else 221 { 222 buffer.append(" "); 223 } 224 buffer.append(' '); 225 } 226 for (int k = 0; k < chars_read; k++) 227 { 228 if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127)) 229 { 230 buffer.append(( char ) data[ k + j ]); 231 } 232 else 233 { 234 buffer.append('.'); 235 } 236 } 237 buffer.append(EOL); 238 display_offset += chars_read; 239 } 240 return buffer.toString(); 241 } 242 243 244 public static final String EOL = 245 System.getProperty("line.separator"); 246 private static final StringBuffer _lbuffer = new StringBuffer(8); 247 private static final StringBuffer _cbuffer = new StringBuffer(2); 248 private static final char _hexcodes[] = 249 { 250 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 251 'E', 'F' 252 }; 253 private static final int _shifts[] = 254 { 255 28, 24, 20, 16, 12, 8, 4, 0 256 }; 257 258 private static String dump(final long value) 259 { 260 _lbuffer.setLength(0); 261 for (int j = 0; j < 8; j++) 262 { 263 _lbuffer 264 .append(_hexcodes[ (( int ) (value >> _shifts[ j ])) & 15 ]); 265 } 266 return _lbuffer.toString(); 267 } 268 269 private static String dump(final byte value) 270 { 271 _cbuffer.setLength(0); 272 for (int j = 0; j < 2; j++) 273 { 274 _cbuffer.append(_hexcodes[ (value >> _shifts[ j + 6 ]) & 15 ]); 275 } 276 return _cbuffer.toString(); 277 } 278 279 /** 280 * Converts the parameter to a hex value. 281 * 282 * @param value The value to convert 283 * @return A String representing the array of bytes 284 */ 285 public static String toHex(final byte[] value) 286 { 287 StringBuffer retVal = new StringBuffer(); 288 retVal.append('['); 289 for(int x = 0; x < value.length; x++) 290 { 291 retVal.append(toHex(value[x])); 292 retVal.append(", "); 293 } 294 retVal.append(']'); 295 return retVal.toString(); 296 } 297 /** 298 * Converts the parameter to a hex value. 299 * 300 * @param value The value to convert 301 * @return The result right padded with 0 302 */ 303 public static String toHex(final short value) 304 { 305 return toHex(value, 4); 306 } 307 308 /** 309 * Converts the parameter to a hex value. 310 * 311 * @param value The value to convert 312 * @return The result right padded with 0 313 */ 314 public static String toHex(final byte value) 315 { 316 return toHex(value, 2); 317 } 318 319 /** 320 * Converts the parameter to a hex value. 321 * 322 * @param value The value to convert 323 * @return The result right padded with 0 324 */ 325 public static String toHex(final int value) 326 { 327 return toHex(value, 8); 328 } 329 330 331 private static String toHex(final long value, final int digits) 332 { 333 StringBuffer result = new StringBuffer(digits); 334 for (int j = 0; j < digits; j++) 335 { 336 result.append( _hexcodes[ (int) ((value >> _shifts[ j + (8 - digits) ]) & 15)]); 337 } 338 return result.toString(); 339 } 340 } 341