Data Type Java

import java.math.BigDecimal;
/*
 *  Dump.java
 *
 *  Projeto ECFbabel
 *
 *  Copyright 2005-2007 Daniel "Spanazzi" Gonçalves
 *  
 *  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 métodos para produção 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 método dump(byte[]) é parecido com o
 *  seguinte exemplo:
 *
 *  

 *    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)
 *  

 *
 *  

Também fornece diversos métodos convenientes para log de dumps hexadecimais.


 *
 *  @since Outubro/2007
 *
 *  @version $Id: Dump.java,v 1.1.1.1 2008/03/12 03:29:34 rawfosgod Exp $
 *
 *  @author Daniel Gonçalves
 */
public final class Dump {
      
            
      
      /**
       *  Constrói um buffer string contendo um dumping 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));
      }
      
      /**
       *  Constrói um buffer string contendo um dumping 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 espaço os valores hexadecimais dos bytes
                              hexDump.append(" ");
                        }
                  }
                  
            }
            
            if ((column != 0) && (column < 15)) {
                  // completa a linha com espaços até a 16a. posição
                  while (column < 16) {
                        hexDump.append("   "); // 3 espaços
                        chrDump.append(" "); // 1 espaço
                        column++;
                  }
                  // remove o último espaço da sequência
                  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 representação hexadecimal do valor.
       *
       *  @param value valor inteiro, de base 10, a ser convertido para base 16.
       *
       *  @param length comprimento total desejado. 
       *
       *  @return Representação 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 representação hexadecimal do valor resultar em um comprimento maior 
       *          que o especificado, a string resultante será formada de asteriscos,
       *          indicando que o comprimento especificado não 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" Gonçalves
 *  
 *  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 Gonçalves
 */
 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:
       *
       *  

       *      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'
       *  

       *
       *  @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:
       * 
       *  

       *  ByteUtils.ascval("ABC", 0); // resulta: 65
       *  ByteUtils.ascval("ABC", 1); // resulta: 66
       *  ByteUtils.ascval("ABC", 2); // resulta: 67
       *  

       *
       *  @param s a string alvo.
       *
       *  @param pos a posição a ser extraído o valor ASCII.
       *
       *  @return o valor ASCII do caracter na posição pos da string
       *          s.
       *
       *  @throws IndexOutOfBoundsException se a posição indicada for menor que zero ou
       *          maior que o tamanho da string s.length() - 1.
       */
      public static int ascval(String s, int pos) {
            return (int)((((byte)(s.charAt(pos))) & 0xff));
      }
      /**
       *  Converte uma string contendo uma sequência decimal codificada em BCD
       *  (Binary-Coded Decimal ?). Esta implementação foi obtida a partir da
       *  descrição da codificação BCD encontrada no manual de programação das 
       *  impressoras fiscais Bematech® MP-20 FI II.
       *
       *  

Se os valores ASCII dos caracteres de uma string forem 0x12, 0x34 e
       *  0x56
, então bcd(s, 2) resultará no valor decimal
       *  1234.56.


       *
       *  @param s a string contendo a sequência BCD.
       *
       *  @param scale o número de casas decimais a serem considerados. Se este
       *         argumento for menor ou igual a zero, será considerado um valor
       *         inteiro.
       *
       *  @return um objeto java.math.BigDecimal contendo o valor
       *          decimal decodificado.
       *
       *  @throws NumberFormatException se a string s não representar
       *          uma sequência BCD válida.
       */
      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 posição de inserção do ponto decimal
                        int count = scale - hexval.length();
                        for (int i = 1; i <= count; i++) hexval.insert(0, "0");
                  }
                  // insere um ponto decimal na posição indicada
                  hexval.insert(hexval.length()-scale, ".");
            }
            return new BigDecimal(hexval.toString());
      }
      
} // {{{ ByteUtils }}}