Coverage Report - org.apache.commons.io.HexDump
 
Classes in this File Line Coverage Branch Coverage Complexity
HexDump
94%
35/37
100%
24/24
4,5
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.io;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.io.OutputStream;
 21  
 import java.nio.charset.Charset;
 22  
 
 23  
 /**
 24  
  * Dumps data in hexadecimal format.
 25  
  * <p>
 26  
  * Provides a single function to take an array of bytes and display it
 27  
  * in hexadecimal form.
 28  
  * <p>
 29  
  * Origin of code: POI.
 30  
  *
 31  
  */
 32  
 public class HexDump {
 33  
 
 34  
     /**
 35  
      * Instances should NOT be constructed in standard programming.
 36  
      */
 37  
     public HexDump() {
 38  0
         super();
 39  0
     }
 40  
 
 41  
     /**
 42  
      * Dump an array of bytes to an OutputStream. The output is formatted
 43  
      * for human inspection, with a hexadecimal offset followed by the
 44  
      * hexadecimal values of the next 16 bytes of data and the printable ASCII
 45  
      * characters (if any) that those bytes represent printed per each line
 46  
      * of output.
 47  
      * <p>
 48  
      * The offset argument specifies the start offset of the data array
 49  
      * within a larger entity like a file or an incoming stream. For example,
 50  
      * if the data array contains the third kibibyte of a file, then the
 51  
      * offset argument should be set to 2048. The offset value printed
 52  
      * at the beginning of each line indicates where in that larger entity
 53  
      * the first byte on that line is located.
 54  
      * <p>
 55  
      * All bytes between the given index (inclusive) and the end of the
 56  
      * data array are dumped.
 57  
      *
 58  
      * @param data  the byte array to be dumped
 59  
      * @param offset  offset of the byte array within a larger entity
 60  
      * @param stream  the OutputStream to which the data is to be
 61  
      *               written
 62  
      * @param index initial index into the byte array
 63  
      *
 64  
      * @throws IOException is thrown if anything goes wrong writing
 65  
      *         the data to stream
 66  
      * @throws ArrayIndexOutOfBoundsException if the index is
 67  
      *         outside the data array's bounds
 68  
      * @throws IllegalArgumentException if the output stream is null
 69  
      */
 70  
 
 71  
     public static void dump(final byte[] data, final long offset,
 72  
                             final OutputStream stream, final int index)
 73  
             throws IOException, ArrayIndexOutOfBoundsException,
 74  
             IllegalArgumentException {
 75  
 
 76  14
         if (index < 0 || index >= data.length) {
 77  4
             throw new ArrayIndexOutOfBoundsException(
 78  
                     "illegal index: " + index + " into array of length "
 79  
                     + data.length);
 80  
         }
 81  10
         if (stream == null) {
 82  2
             throw new IllegalArgumentException("cannot write to nullstream");
 83  
         }
 84  8
         long display_offset = offset + index;
 85  8
         final StringBuilder buffer = new StringBuilder(74);
 86  
 
 87  120
         for (int j = index; j < data.length; j += 16) {
 88  112
             int chars_read = data.length - j;
 89  
 
 90  112
             if (chars_read > 16) {
 91  104
                 chars_read = 16;
 92  
             }
 93  112
             dump(buffer, display_offset).append(' ');
 94  1904
             for (int k = 0; k < 16; k++) {
 95  1792
                 if (k < chars_read) {
 96  1790
                     dump(buffer, data[k + j]);
 97  
                 } else {
 98  2
                     buffer.append("  ");
 99  
                 }
 100  1792
                 buffer.append(' ');
 101  
             }
 102  1902
             for (int k = 0; k < chars_read; k++) {
 103  1790
                 if (data[k + j] >= ' ' && data[k + j] < 127) {
 104  570
                     buffer.append((char) data[k + j]);
 105  
                 } else {
 106  1220
                     buffer.append('.');
 107  
                 }
 108  
             }
 109  112
             buffer.append(EOL);
 110  
             // make explicit the dependency on the default encoding
 111  112
             stream.write(buffer.toString().getBytes(Charset.defaultCharset()));
 112  112
             stream.flush();
 113  112
             buffer.setLength(0);
 114  112
             display_offset += chars_read;
 115  
         }
 116  8
     }
 117  
 
 118  
     /**
 119  
      * The line-separator (initializes to "line.separator" system property.
 120  
      */
 121  2
     public static final String EOL =
 122  
             System.getProperty("line.separator");
 123  2
     private static final char[] _hexcodes =
 124  
             {
 125  
                 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 126  
                 'A', 'B', 'C', 'D', 'E', 'F'
 127  
             };
 128  2
     private static final int[] _shifts =
 129  
             {
 130  
                 28, 24, 20, 16, 12, 8, 4, 0
 131  
             };
 132  
 
 133  
     /**
 134  
      * Dump a long value into a StringBuilder.
 135  
      *
 136  
      * @param _lbuffer the StringBuilder to dump the value in
 137  
      * @param value  the long value to be dumped
 138  
      * @return StringBuilder containing the dumped value.
 139  
      */
 140  
     private static StringBuilder dump(final StringBuilder _lbuffer, final long value) {
 141  1008
         for (int j = 0; j < 8; j++) {
 142  896
             _lbuffer
 143  
                     .append(_hexcodes[(int) (value >> _shifts[j]) & 15]);
 144  
         }
 145  112
         return _lbuffer;
 146  
     }
 147  
 
 148  
     /**
 149  
      * Dump a byte value into a StringBuilder.
 150  
      *
 151  
      * @param _cbuffer the StringBuilder to dump the value in
 152  
      * @param value  the byte value to be dumped
 153  
      * @return StringBuilder containing the dumped value.
 154  
      */
 155  
     private static StringBuilder dump(final StringBuilder _cbuffer, final byte value) {
 156  5370
         for (int j = 0; j < 2; j++) {
 157  3580
             _cbuffer.append(_hexcodes[value >> _shifts[j + 6] & 15]);
 158  
         }
 159  1790
         return _cbuffer;
 160  
     }
 161  
 
 162  
 }