Java 如何将字节数组转换为人类可读的格式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4141317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:01:34  来源:igfitidea点击:

How to convert byte array into Human readable format?

java

提问by Supereme

I am using "Blowfish" algorithm to encrypt and decrypt the contents of the text. I am embedding the encrypted contents in the image but while extracting I am getting the byte array which I am passing it to method updateof class Cipher.

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

But the method returns me byte array which I want to convert back into Human readable form.
When I use writemethod of FileOutputStreamit is working fine when a filename is provided.
But now I want to print it on the console in the human readable format. How to get through this? I have tried for ByteArrayOutputStream too. But didn't work well.

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

Thank you.

谢谢你。

采纳答案by Barun

byte[] byteArray = new byte[] {87, 79, 87, 46, 46, 46};

String value = new String(byteArray);

回答by Mark Elliot

If all you want to do is see the numeric values you can loop through the array and print each byte:

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

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

Or if you want to see hex values you can use printf:

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

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

If you want to see the string that the byte array represents you can just do

如果您想查看字节数组表示的字符串,您可以这样做

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

回答by Nikolaus Gradwohl

You can convert the bytearray into a string containing the hex values of the bytes using this method. This even works on java < 6

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

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();
    }   
}

回答by Tag

byte[] data = new byte[] {1, 2, 3, 4};
System.out.printf( Arrays.toString( data ) );

[1, 2, 3, 4]

回答by secmask

It's better to do a hexDump that byte array

最好做一个 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();
    }

回答by Stan Sokolov

It is not a trivial task, as many people assume. Each byte has values ranging from -128 to 127. Most of them are non printable characters.

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

In order to encode bytes in a human readable format you should understand that there is only 62 alphanumeric characters. There is no way ONE BYTE will map to ONE human readable characters as there is more possible bytes than 62 characters human can easily read.

为了以人类可读的格式对字节进行编码,您应该了解只有 62 个字母数字字符。一个字节不可能映射到一个人类可读的字符,因为可能的字节多于人类可以轻松读取的 62 个字符。

Bellow is a class I wrote that converts a byte array into a String using provided alphabet (or a default if none provided).

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

It does conversion in chunks from 1 to 7 input bytes. Could not use more than 7 bytes is it is max for the biggest Java long value. And I use long values when do conversion.

它从 1 到 7 个输入字节的块中进行转换。不能使用超过 7 个字节,这是最大 Java 长值的最大值。我在转换时使用长值。

If chunk for example of size 5 than it needs 7 alphanumeric symbols to encode a chunk of 5 bytes. So size of output will be greater than size of input.

如果块例如大小为 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));
}
}