【问题标题】:How to convert byte array into Human readable format?如何将字节数组转换为人类可读的格式?
【发布时间】:2010-11-10 04:48:54
【问题描述】:

我正在使用“Blowfish”算法来加密和解密文本的内容。我在图像中嵌入了加密的内容,但是在提取时我得到了字节数组,我将它传递给类 Cipher 的方法 update

但是该方法返回我想要转换回人类可读形式的字节数组。
当我使用 FileOutputStreamwrite 方法时,它在提供文件名时工作正常。
但现在我想以人类可读的格式在控制台上打印它。如何度过这个难关?我也尝试过 ByteArrayOutputStream 。但效果并不好。

谢谢。

【问题讨论】:

  • 谢谢大家,对我帮助很大。

标签: java


【解决方案1】:

如果您只想查看数值,您可以遍历数组并打印每个字节:

for(byte foo : arr){
    System.out.print(foo + " ");
}

或者如果你想查看十六进制值,你可以使用printf:

System.out.printf("%02x ", foo);

如果你想查看字节数组所代表的字符串,你可以这样做

System.out.print(new String(arr));

【讨论】:

    【解决方案2】:
    byte[] byteArray = new byte[] {87, 79, 87, 46, 46, 46};
    
    String value = new String(byteArray);
    

    【讨论】:

    • 恕我直言,Blowfish 返回的字节数组可以返回完整字节范围内的字节值。此答案当前显示了“人类可读子范围”中的示例字节数组。使用new String(byteArray); 不一定(通常)会产生人类可读的字符串。
    • 它不一定会产生“人类可读的字符串”。就我而言,它会生成许多非键盘字符。我使用了DESede 算法。
    • 人类无法阅读。字节范围是 -128 .. 127。负数和 64 岁以上的所有内容都会产生垃圾
    【解决方案3】:

    您可以将字节数组转换为包含字节的十六进制值的字符串 使用这种方法。这甚至适用于 java

    public class DumpUtil {
    
         private static final String HEX_DIGITS = "0123456789abcdef";
    
         public static String toHex(byte[] data) {
            StringBuffer buf = new StringBuffer();
    
            for (int i = 0; i != data.length; i++) {
                int v = data[i] & 0xff;
    
                buf.append(HEX_DIGITS.charAt(v >> 4));
                buf.append(HEX_DIGITS.charAt(v & 0xf));
    
                buf.append(" ");
            }
    
            return buf.toString();
        }   
    }
    

    【讨论】:

      【解决方案4】:
      byte[] data = new byte[] {1, 2, 3, 4};
      System.out.printf( Arrays.toString( data ) );
      
      [1, 2, 3, 4]
      

      【讨论】:

        【解决方案5】:

        最好对那个字节数组做一个hexDump

        private static final byte[] HEX_CHAR = new byte[] { '0', '1', '2', '3',
                    '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        public static final String dumpBytes(byte[] buffer) {
                if (buffer == null) {
                    return "";
                }
                StringBuilder sb = new StringBuilder();
                sb.setLength(0);
                for (int i = 0; i < buffer.length; i++) {
                    sb.append((char) (HEX_CHAR[(buffer[i] & 0x00F0) >> 4]))
                            .append((char) (HEX_CHAR[buffer[i] & 0x000F])).append(' ');
                }
                return sb.toString();
            }
        

        【讨论】:

          【解决方案6】:

          正如许多人所认为的那样,这不是一项微不足道的任务。每个字节的值范围从 -128 到 127。其中大多数是不可打印的字符。

          为了以人类可读的格式对字节进行编码,您应该了解只有 62 个字母数字字符。 ONE BYTE 无法映射到 ONE 人类可读的字符,因为可能的字节数超过了人类可以轻松阅读的 62 个字符。

          Bellow 是我编写的一个类,它使用提供的字母表(如果没有提供,则使用默认值)将字节数组转换为字符串。

          它以 1 到 7 个输入字节的块进行转换。不能使用超过 7 个字节是最大 Java long 值的最大值。而且我在进行转换时使用长值。

          如果块大小为 5,则它需要 7 个字母数字符号来编码 5 个字节的块。所以输出的大小将大于输入的大小。

          import org.slf4j.Logger;
          
          /**************************************************************************************************************
           * Convert bytes into human readable string using provided alphabet.
           * If alphabet size 62 chars and byte chunk is 5 bytes then we need 7 symbols to encode it.
           * So input size will be increased by 40% plus 7 symbols to encode length of input
           *
           * Basically we do conversion from base255 (byte can has 255 different symbols) to base of a a size of the
           * given alphabet
           *
           * @author Stan Sokolov
           * 10/9/19
           **************************************************************************************************************/
          public class HumanByte {
          final static private Logger logger = org.slf4j.LoggerFactory.getLogger(OsmRouting.class);
          
          // those are chars we use for encoding
          private final static String DEFAULT_ALPHABET = "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
          
          private char[] ALPHABET;
          private int BASE;
          private int[] POSITIONS;
          private int CHUNK;
          private int PW;
          private long[] POWERS; // {916132832, 14776336, 238328, 3844, 62, 1};
          private long[] MASKS; //(0xFF000000L & (input[0] << 24)) | (0xFF0000L & input[1] << 16) | (0xFF00L & input[2] << 8) | (0xFFL & input[3]);
          
          
          /**************************************************************************************************************
           * Default constructor, with default alphabet and default chunk
           **************************************************************************************************************/
          public HumanByte() {
              this(DEFAULT_ALPHABET, 5);
          }
          
          /**************************************************************************************************************
           *   Setup encoding using provided alphabet and chunk size
           **************************************************************************************************************/
          public HumanByte(final String alphabet, int chunk) {
              if (chunk>7){
                  chunk=7;
              }
              if (chunk<1){
                  chunk=1;
              }
              this.ALPHABET = alphabet.toCharArray();
              BASE = alphabet.length();
          
              CHUNK = chunk;
              long MX = (long) Math.pow(255, CHUNK);
              PW = logBase(MX);
              int max=0;
              for (int i = 0; i < ALPHABET.length; i++) {
                  if (max<ALPHABET[i]) max=ALPHABET[i];
              }
              POSITIONS = new int[max+1];
              logger.debug("BASE={}, MX={}, PW={}", BASE, MX, PW);
              for (int i = 0; i < ALPHABET.length; i++) {
                  POSITIONS[ALPHABET[i]] = i;
              }
              POWERS = new long[PW]; //these are the powers of base to split input number into digits of its base
              for (int i = 0; i < PW; i++) {
                  POWERS[i] = (long) Math.pow(BASE, PW - i - 1);
              }
              MASKS = new long[CHUNK];
              for (int i = 0; i < CHUNK; i++) { //this is how we are going to extract individual bytes from chunk
                  MASKS[i] = (0xFFL << ((CHUNK - i - 1) * 8));
              }
          }
          
          
          /**************************************************************************************************************
           *  take bytes, split them in group by CHUNK, encode each group in PW number of alphabet symbols.
           **************************************************************************************************************/
          public String encode(final byte[] input) {
              final StringBuilder output = new StringBuilder(); //will save output string here
              output.append(word(input.length)); // first write length of input into output to know exact size
          
              byte[] byte_word;
              for (int i = 0; i < input.length; ) {
                  byte_word = new byte[CHUNK];
                  for (int j = 0; j < CHUNK; j++) {
                      if (i < input.length) {
                          byte_word[j] = input[i++]; //remove negatives
                      }
                  }
                  final long n = bytes2long(byte_word); //1099659687880
          
                  final char[] w = word(n);
                  output.append(w);
          
              }
              return output.toString();
          }
          
          /**************************************************************************************************************
           *   decode input
           **************************************************************************************************************/
          public byte[] decode(final String in) {
              final int size = (int) number(in.substring(0, PW).toCharArray());
              final byte[] output = new byte[size];
          
              int j = 0, k = in.length();
              for (int i = PW; i < k; i += PW) {
                  final String w = in.substring(i, i + PW);
                  final long n = number(w.toCharArray());
                  for (byte b : long2bytes(n)) {
                      if (j < size) {
                          output[j++] = b;
                      }
                  }
              }
              return output;
          }
          
          /**************************************************************************************************************
           * @return take 4 numbers from 0 to 255 and convert them in long
           **************************************************************************************************************/
          private long bytes2long(byte[] input) {
              long v = 0;
              for (int i = 0; i < CHUNK; i++) {
                  v |= ((long) (input[i]+ 128) << (8 * (CHUNK - i - 1)) & MASKS[i]); //+128 to remove negatives
              }
              return v;
          }
          
          /**************************************************************************************************************
           * @return take 4 numbers from 0 to 255 and convert them in long
           **************************************************************************************************************/
          private byte[] long2bytes(long input) {
              final byte[] bytes = new byte[CHUNK];
              for (int i = 0; i < CHUNK; i++) {
                  long x = MASKS[i] & input;
                  long y = 8 * (CHUNK - i - 1);
                  long z = (x >> y) - 128;
                  bytes[i] = (byte) z;
              }
              return bytes;
          }
          
          
          /**************************************************************************************************************
           *  create word using given alphabet to represent given number built out of CHUNK bytes
           **************************************************************************************************************/
          private char[] word(final long n) {
              final char[] output = new char[PW];
              long v=n;
              for (int i = 0; i < PW; i++) {
                  final long pn = v / POWERS[i];
                  output[i] = ALPHABET[(int) pn];
                  long x = pn * POWERS[i];//900798402816 196327857024 2368963584 16134768 267696 1716 52
                  v -= x;
              }
              return output;
          }
          
          /**************************************************************************************************************
           *   take string that contain number encoded in alphabet and return
           **************************************************************************************************************/
          private long number(final char[] s) {
              long number = 0;
              for (int i = 0; i < PW; i++) {
                  long x =  (long) POSITIONS[s[i]];
                  long y = POWERS[i];
                  long z = x*y;
                  number +=  z;
              }
              return number;
          }
          
          private int logBase(long num) {
              return (int) Math.ceil(Math.log(num) / Math.log(BASE));
          }
          }
          

          【讨论】:

            猜你喜欢
            • 2011-04-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-20
            • 2014-12-24
            • 2018-04-22
            • 1970-01-01
            • 2023-03-23
            相关资源
            最近更新 更多