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

Java 如何将字节数组转换为人类可读的格式?,java,Java,我使用“河豚”算法对文本内容进行加密和解密。我将加密内容嵌入到图像中,但在提取时,我得到字节数组,并将其传递给类Cipher的方法update 但该方法返回我想要转换回人类可读形式的字节数组。 当我使用FileOutputStream的write方法时,当提供文件名时,它工作正常。 但现在我想在控制台上以人类可读的格式打印它。如何度过这一关?我也试过ByteArrayOutputStream。但效果不好 谢谢。如果您只想看到数值,您可以在数组中循环并打印每个字节: for(byte foo :

我使用“河豚”算法对文本内容进行加密和解密。我将加密内容嵌入到图像中,但在提取时,我得到字节数组,并将其传递给类Cipher的方法update

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


谢谢。

如果您只想看到数值,您可以在数组中循环并打印每个字节:

for(byte foo : arr){
    System.out.print(foo + " ");
}
或者,如果要查看十六进制值,可以使用
printf

System.out.printf("%02x ", foo);
如果想查看字节数组表示的字符串,只需执行以下操作

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

您可以将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();
    }   
}

最好对字节数组进行十六进制转储

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();
    }
private static final byte[]HEX_CHAR=新字节[]{'0','1','2','3',
‘4’、‘5’、‘6’、‘7’、‘8’、‘9’、‘A’、‘B’、‘C’、‘D’、‘E’、‘F’};
公共静态最终字符串转储字节(字节[]缓冲区){
if(buffer==null){
返回“”;
}
StringBuilder sb=新的StringBuilder();
sb.设定长度(0);
for(int i=0;i>4]))
.append((字符)(十六进制字符[buffer[i]和0x000F])).append(“”);
}
使某人返回字符串();
}

这并不像许多人认为的那样是一项琐碎的任务。每个字节的值范围为-128到127。其中大多数是不可打印的字符

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

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

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

例如,如果区块大小为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));
}
}
import org.slf4j.Logger;
/**************************************************************************************************************
*使用提供的字母表将字节转换为人类可读的字符串。
*如果字母表大小为62个字符,字节块为5个字节,那么我们需要7个符号对其进行编码。
*所以输入大小将增加40%,加上7个符号来编码输入的长度
*
*基本上,我们从base255(字节可以有255个不同的符号)转换到大小为
*给定字母表
*
*@作者斯坦·索科洛夫
* 10/9/19
**************************************************************************************************************/
公共类人形字节{
最终静态私有记录器Logger=org.slf4j.LoggerFactory.getLogger(OsmRouting.class);
//这些是我们用来编码的字符
私有最终静态字符串默认值_ALPHABET=“0123456789QWERTYUIOPASDFGHJKLZXCVNMQWERTYUIOPASDFGHJKLZXCVBNM”;
私人字符[]字母表;
私人int基地;
私人职位;
私有int块;
私人int PW;
私人长[]权力;/{916132832、14776336、238328、3844、62、1};

private long[]MASKS;//(0xFF000000L&(input[0]谢谢大家,它帮了我很多忙。嗯,河豚返回的字节数组可以返回整个字节范围内的字节值。这个答案目前显示了“人类可读子范围”中的一个字节数组示例。使用
新字符串(byteArray);
不一定(通常)生成人类可读的字符串。它不一定会生成“人类可读的字符串”。在我的例子中,它会生成许多非键盘字符。我使用了
DESede
算法。它不会是人类可读的。字节范围是-128..127。负数和所有64+都会生成垃圾
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();
    }
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));
}
}