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 * 85 * @exception IOException is thrown if anything goes wrong writing 86 * the data to stream 87 * @exception ArrayIndexOutOfBoundsException if the index is 88 * outside the data array's bounds 89 * @exception IllegalArgumentException if the output stream is 90 * null 91 */ 92 93 public synchronized static void dump(final byte [] data, final long offset, 94 final OutputStream stream, final int index) 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 for (int j = index; j < data.length; j += 16) 112 { 113 int chars_read = data.length - j; 114 115 if (chars_read > 16) 116 { 117 chars_read = 16; 118 } 119 buffer.append(dump(display_offset)).append(' '); 120 for (int k = 0; k < 16; k++) 121 { 122 if (k < chars_read) 123 { 124 buffer.append(dump(data[ k + j ])); 125 } 126 else 127 { 128 buffer.append(" "); 129 } 130 buffer.append(' '); 131 } 132 for (int k = 0; k < chars_read; k++) 133 { 134 if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127)) 135 { 136 buffer.append(( char ) data[ k + j ]); 137 } 138 else 139 { 140 buffer.append('.'); 141 } 142 } 143 buffer.append(EOL); 144 stream.write(buffer.toString().getBytes()); 145 stream.flush(); 146 buffer.setLength(0); 147 display_offset += chars_read; 148 } 149 } 150 151 /** 152 * dump an array of bytes to a String 153 * 154 * @param data the byte array to be dumped 155 * @param offset its offset, whatever that might mean 156 * @param index initial index into the byte array 157 * 158 * @exception IOException is thrown if anything goes wrong writing 159 * the data to stream 160 * @exception ArrayIndexOutOfBoundsException if the index is 161 * outside the data array's bounds 162 * @return output string 163 */ 164 165 public static String dump(final byte [] data, final long offset, 166 final int index) { 167 StringBuffer buffer; 168 if ((index < 0) || (index >= data.length)) 169 { 170 throw new ArrayIndexOutOfBoundsException( 171 "illegal index: " + index + " into array of length " 172 + data.length); 173 } 174 long display_offset = offset + index; 175 buffer = new StringBuffer(74); 176 177 for (int j = index; j < data.length; j += 16) 178 { 179 int chars_read = data.length - j; 180 181 if (chars_read > 16) 182 { 183 chars_read = 16; 184 } 185 buffer.append(dump(display_offset)).append(' '); 186 for (int k = 0; k < 16; k++) 187 { 188 if (k < chars_read) 189 { 190 buffer.append(dump(data[ k + j ])); 191 } 192 else 193 { 194 buffer.append(" "); 195 } 196 buffer.append(' '); 197 } 198 for (int k = 0; k < chars_read; k++) 199 { 200 if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127)) 201 { 202 buffer.append(( char ) data[ k + j ]); 203 } 204 else 205 { 206 buffer.append('.'); 207 } 208 } 209 buffer.append(EOL); 210 display_offset += chars_read; 211 } 212 return buffer.toString(); 213 } 214 215 216 public static final String EOL = 217 System.getProperty("line.separator"); 218 private static final StringBuffer _lbuffer = new StringBuffer(8); 219 private static final StringBuffer _cbuffer = new StringBuffer(2); 220 private static final char _hexcodes[] = 221 { 222 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 223 'E', 'F' 224 }; 225 private static final int _shifts[] = 226 { 227 28, 24, 20, 16, 12, 8, 4, 0 228 }; 229 230 private static StringBuffer dump(final long value) 231 { 232 _lbuffer.setLength(0); 233 for (int j = 0; j < 8; j++) 234 { 235 _lbuffer 236 .append(_hexcodes[ (( int ) (value >> _shifts[ j ])) & 15 ]); 237 } 238 return _lbuffer; 239 } 240 241 private static StringBuffer dump(final byte value) 242 { 243 _cbuffer.setLength(0); 244 for (int j = 0; j < 2; j++) 245 { 246 _cbuffer.append(_hexcodes[ (value >> _shifts[ j + 6 ]) & 15 ]); 247 } 248 return _cbuffer; 249 } 250 251 /** 252 * Converts the parameter to a hex value. 253 * 254 * @param value The value to convert 255 * @return A String representing the array of bytes 256 */ 257 public static String toHex(final byte[] value) 258 { 259 StringBuffer retVal = new StringBuffer(); 260 retVal.append('['); 261 for(int x = 0; x < value.length; x++) 262 { 263 retVal.append(toHex(value[x])); 264 retVal.append(", "); 265 } 266 retVal.append(']'); 267 return retVal.toString(); 268 } 269 /** 270 * Converts the parameter to a hex value. 271 * 272 * @param value The value to convert 273 * @return The result right padded with 0 274 */ 275 public static String toHex(final short value) 276 { 277 return toHex(value, 4); 278 } 279 280 /** 281 * Converts the parameter to a hex value. 282 * 283 * @param value The value to convert 284 * @return The result right padded with 0 285 */ 286 public static String toHex(final byte value) 287 { 288 return toHex(value, 2); 289 } 290 291 /** 292 * Converts the parameter to a hex value. 293 * 294 * @param value The value to convert 295 * @return The result right padded with 0 296 */ 297 public static String toHex(final int value) 298 { 299 return toHex(value, 8); 300 } 301 302 303 private static String toHex(final long value, final int digits) 304 { 305 StringBuffer result = new StringBuffer(digits); 306 for (int j = 0; j < digits; j++) 307 { 308 result.append( _hexcodes[ (int) ((value >> _shifts[ j + (8 - digits) ]) & 15)]); 309 } 310 return result.toString(); 311 } 312 } 313