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