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