Mega Code Archive

 
Categories / Java / Data Type
 

Hex decimal dump

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 <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>Também fornece diversos métodos 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 Gonçalves  */ public final class Dump {                                  /**        *  Constrói 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));       }              /**        *  Constrói 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 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:        *        *  <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 posição a ser extraído o valor ASCII.        *        *  @return o valor ASCII do caracter na posição <code>pos</code> da string        *          <code>s</code>.        *        *  @throws IndexOutOfBoundsException se a posição 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 sequência decimal codificada em BCD        *  (<em>Binary-Coded Decimal</em> ?). Esta implementação foi obtida a partir da        *  descrição da codificação BCD encontrada no manual de programação 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>, então <code>bcd(s, 2)</code> resultará no valor decimal        *  <code>1234.56</code>.</p>        *        *  @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 <code>java.math.BigDecimal</code> contendo o valor        *          decimal decodificado.        *        *  @throws NumberFormatException se a string <code>s</code> 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 }}}