Dump.java Source code

Java tutorial

Introduction

Here is the source code for Dump.java

Source

import java.math.BigDecimal;

/*
 *  Dump.java
 *
 *  Projeto ECFbabel
 *
 *  Copyright 2005-2007 Daniel "Spanazzi" Gonalves
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 *  Fornece mtodos para produo de dumps hexadecimais a partir de arrays de bytes ou 
 *  de inteiros (inteiros representando bytes sem sinal, entre 0 e 255). Um dump 
 *  hexadecimal produzido pelo mtodo <code>dump(byte[])</code>  parecido com o
 *  seguinte exemplo:
 *
 *  <pre>
 *    Titulo do dump aqui
 *    000000  38 19 4A 14 F9 12 91 52-73 89 BA F9 F3 2E 00 CC  8.J....Rs.......
 *    000010  FB 37 7A 88 35 87 30 47-39 C1 DD D6 C9 F5 1F 11  .7z.5.0G9.......
 *    000020  E6 A6 C1 7D 4E 27 C1 A6-55 17 99 34 19 17 30 C9  ...}N'..U..4..0.
 *    000030  CC 68 C4 2B 74 2B 83 9D-59 15 3B 86 B9 F1 9D 07  .h.+t+..Y.;.....
 *    000040  9F 14 99 AE C6 A2 C6 40-EC 27 2C 55 61 F7 2A 63  .......@.',Ua.*c
 *    000050  8C AD 82 22 68 11 CE 24-41 9C 8B 93 DA AA 62 3C  ..."h..$A.....b<
 *    000060  C5 17 BD 49 6F 19 E4 F7-9D 3B 4C 33 14 15 81 66  ...Io....;L3...f
 *    000070  97 BA A4 29 70 B2 81 04-35 08 AA 6D 8D 6E 6F 54  ...)p...5..m.noT
 *    000080  9C DA 6A 28 F6 B4 C2 D7-BD 01 D0 6C D7 CC 8D 04  ..j(.......l....
 *    000090  29 BA 0F 87 21 B2 99 52-7B E5 19 5C 4D F7 6A 32  )...!..R{..\M.j2
 *    0000A0  36 A4 77 58 33 67 54 EF-C0 62 3F 19 29 D6 A7 A2  6.wX3gT..b?.)...
 *    0000B0  77 54 B0 3E DE 3E 83 1B-FE 22 4E EF 8C F7 99 88  wT.>.>..."N.....
 *    0000C0  55 6B CE 9E 75 A3 50 B7-FA A5 59 2A 41 34 7D 56  Uk..u.P...Y*A4}V
 *    0000D0  FA E6 FD 0A 77 36 C5 52-C4 E3                    ....w6.R..
 *    Dump: 218 byte(s)
 *  </pre>
 *
 *  <p>Tambm fornece diversos mtodos convenientes para log de dumps hexadecimais.</p>
 *
 *  @since Outubro/2007
 *
 *  @version $Id: Dump.java,v 1.1.1.1 2008/03/12 03:29:34 rawfosgod Exp $
 *
 *  @author Daniel Gonalves
 */
public final class Dump {

    /**
     *  Constri um buffer string contendo um <em>dumping</em> hexadecimal do array de
     *  inteiros.
     *
     *  @param data array de inteiros. Cada elemento do array dever ser um valor
     *         que represente um byte sem sinal, entre 0 e 255, inclusive.
     */
    public static String dump(final int[] data) {
        return dump(ByteUtils.itob(data));
    }

    /**
     *  Constri um buffer string contendo um <em>dumping</em> hexadecimal do array de
     *  bytes especificado.
     *
     *  @param data array de dados.
     *
     *  @return buffer string contendo o dump hexadecimal.
     */
    public static String dump(final byte[] data) {

        String eol = System.getProperty("line.separator");
        StringBuilder buffer = new StringBuilder();

        int offset = 0;
        int column = 0;

        StringBuilder hexDump = new StringBuilder();
        StringBuilder chrDump = new StringBuilder();

        for (int pos = 0; pos < data.length; pos++) {

            hexDump.append(hex((int) (data[pos] & 0xff), 2));
            chrDump.append(chr((int) (data[pos] & 0xff)));

            column++;

            if (column > 15) {
                buffer.append("  ").append(hex(offset, 6)).append("  ").append(hexDump).append("  ").append(chrDump)
                        .append(eol);

                column = 0;
                offset += 16;

                hexDump = new StringBuilder();
                chrDump = new StringBuilder();
            } else {
                if (column == 8) {
                    // inclui um separador "-" entre a 8a. e 9a. colunas
                    hexDump.append("-");
                } else {
                    // separa com 1 espao os valores hexadecimais dos bytes
                    hexDump.append(" ");
                }
            }

        }

        if ((column != 0) && (column < 15)) {
            // completa a linha com espaos at a 16a. posio
            while (column < 16) {
                hexDump.append("   "); // 3 espaos
                chrDump.append(" "); // 1 espao
                column++;
            }
            // remove o ltimo espao da sequncia
            hexDump.deleteCharAt(hexDump.length() - 1);
            buffer.append("  ").append(hex(offset, 6)).append("  ").append(hexDump).append("  ").append(chrDump)
                    .append(eol);
        }

        // inclui o rodap, indicando o total de bytes no dump
        buffer.append("  Dump: ").append(data.length).append(" byte(s).").append(eol);

        return buffer.toString();

    } // dump(byte[])

    /**
     *  Retorna uma string de tamanho fixo, contendo a representao hexadecimal do valor.
     *
     *  @param value valor inteiro, de base 10, a ser convertido para base 16.
     *
     *  @param length comprimento total desejado. 
     *
     *  @return Representao hexadecimal do valor com o comprimento especificado.
     *          A string resultante ser completada com zeros  esquerda at que o
     *          comprimento total desejado seja atingido.
     *          Se a representao hexadecimal do valor resultar em um comprimento maior 
     *          que o especificado, a string resultante ser formada de asteriscos,
     *          indicando que o comprimento especificado no foi suficiente para o valor. 
     */
    public static String hex(final int value, final int length) {
        StringBuilder str = new StringBuilder(Integer.toString(value, 16).toUpperCase());
        if (str.length() < length) {
            int falta = (length - str.length());
            for (int i = 1; i <= falta; i++) {
                str.insert(0, "0");
            }
        } else if (str.length() > length) {
            str = new StringBuilder();
            for (int i = 1; i <= length; i++) {
                str.append("*");
            }
        }
        return str.toString();
    }

    private static String chr(final int value) {
        if ((value < 32) || (value > 127)) {
            return ".";
        }
        return new String(new byte[] { (byte) (value & 0xff) });
    }

} // {{{ Dump }}}
/*
 *  ByteUtils.java
 *
 *  Projeto ECFbabel
 *
 *  Copyright 2005-2007 Daniel "Spanazzi" Gonalves
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 *  TODO: documentar!  
 *
 *  @since Setembro/2007
 *
 *  @version $Id: ByteUtils.java,v 1.1.1.1 2008/03/12 03:29:33 rawfosgod Exp $
 *
 *  @author Daniel Gonalves
 */
final class ByteUtils {

    private ByteUtils() {
    }

    /**
     *  Retorna o byte de baixa ordem a partir de um valor inteiro.
     *
     *  @param value valor inteiro (at 65535).
     *
     *  @return byte de baixa ordem do valor. Por exemplo, o byte de
     *          baixa ordem para o valor 1234  210.
     */
    public static int lo(final int value) {
        int low = value;
        if (value > 255)
            low = Math.abs(value % 256);
        return low;
    }

    /**
     *  Retorna o byte de alta ordem a partir de um valor inteiro.
     * 
     *  @param value valor inteiro (at 65535).
     *
     *  @return byte de alta ordem do valor. Por exemplo, o byte de 
     *          alta ordem para o valor 1234  4.
     */
    public static int hi(final int value) {
        int high = 0;
        if (value > 255)
            high = Math.abs((int) (value / 256));
        return high;
    }

    /**
     *  Converte 2 bytes sem sinal no formato Intel Low/High para um inteiro.
     *  Como no exemplo:
     *
     *  <pre>
     *      int valor = 1234; // '100 1101 0010'
     *      int hi = ByteUtils.hi(valor);  // resulta: 4  '100'
     *      int lo = ByteUtils.lo(valor);  // resulta: 210  '1101 0010'
     *      int test = ByteUtils.hilo2int(hi, lo) // resulta: 1234  '100 1101 0010'
     *  </pre>
     *
     *  @param high byte de alta ordem (deve ser um valor entre 0 e 255 inclusive).
     *  @param low byte de baixa ordem (deve ser um valor entre 0 e 255 inclusive).
     *
     *  @return valor inteiro at 65535 representados pelos bytes de alta e baixa ordem. 
     */
    public static int hilo2int(int high, int low) {
        return (low | (high << 8));
    }

    public static byte[] itob(int[] ints) {
        byte[] bytes = new byte[ints.length];
        for (int i = 0; i < ints.length; i++)
            bytes[i] = (byte) (ints[i] & 0xff);
        return bytes;
    }

    public static int[] btoi(byte[] bytes) {
        int[] ints = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++)
            ints[i] = (int) (bytes[i] & 0xff);
        return ints;
    }

    /**
     *  Extrai o valor ASCII de um determinado caracter de uma string. Por exemplo:
     * 
     *  <pre>
     *  ByteUtils.ascval("ABC", 0); // resulta: 65
     *  ByteUtils.ascval("ABC", 1); // resulta: 66
     *  ByteUtils.ascval("ABC", 2); // resulta: 67
     *  </pre>
     *
     *  @param s a string alvo.
     *
     *  @param pos a posio a ser extrado o valor ASCII.
     *
     *  @return o valor ASCII do caracter na posio <code>pos</code> da string
     *          <code>s</code>.
     *
     *  @throws IndexOutOfBoundsException se a posio indicada for menor que zero ou
     *          maior que o tamanho da string <code>s.length() - 1</code>.
     */
    public static int ascval(String s, int pos) {
        return (int) ((((byte) (s.charAt(pos))) & 0xff));
    }

    /**
     *  Converte uma string contendo uma sequncia decimal codificada em BCD
     *  (<em>Binary-Coded Decimal</em> ?). Esta implementao foi obtida a partir da
     *  descrio da codificao BCD encontrada no manual de programao das 
     *  impressoras fiscais Bematech&reg; MP-20 FI II.
     *
     *  <p>Se os valores ASCII dos caracteres de uma string forem <code>0x12, 0x34 e
     *  0x56</code>, ento <code>bcd(s, 2)</code> resultar no valor decimal
     *  <code>1234.56</code>.</p>
     *
     *  @param s a string contendo a sequncia BCD.
     *
     *  @param scale o nmero de casas decimais a serem considerados. Se este
     *         argumento for menor ou igual a zero, ser considerado um valor
     *         inteiro.
     *
     *  @return um objeto <code>java.math.BigDecimal</code> contendo o valor
     *          decimal decodificado.
     *
     *  @throws NumberFormatException se a string <code>s</code> no representar
     *          uma sequncia BCD vlida.
     */
    public static BigDecimal bcd(final String s, final int scale) {

        StringBuilder hexval = new StringBuilder();

        // converte os valores ASCII da string para hexadecimal
        for (int i = 0; i < s.length(); i++) {
            StringBuilder hex = new StringBuilder(Integer.toString(ascval(s, i), 16));
            if (hex.length() != 2)
                hex.insert(0, "0");
            hexval.append(hex);
        }

        if (scale > 0) {
            if (scale > hexval.length()) {
                // completa com zeros antes da posio de insero do ponto decimal
                int count = scale - hexval.length();
                for (int i = 1; i <= count; i++)
                    hexval.insert(0, "0");
            }
            // insere um ponto decimal na posio indicada
            hexval.insert(hexval.length() - scale, ".");
        }

        return new BigDecimal(hexval.toString());

    }

} // {{{ ByteUtils }}}