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

时间:2010-11-10 04:48:55

标签: java

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

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

谢谢。

6 个答案:

答案 0 :(得分:7)

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

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

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

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

如果要查看字节数组所代表的字符串,可以执行

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

答案 1 :(得分: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();
    }   
}

答案 2 :(得分:5)

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

String value = new String(byteArray);

答案 3 :(得分:3)

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

[1, 2, 3, 4]

答案 4 :(得分:0)

最好做一个十六进制字节数组

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

答案 5 :(得分:0)

这不是很多人认为的琐碎的任务。每个字节的值范围从-128到127。其中大多数是不可打印的字符。

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

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

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