如何在Java中将字节数组转换为hexstring?

我有一个字节数组填充hex数字和打印它简单的方法是非常毫无意义,因为有许多不可打印的元素。 我需要的是以下forms的确切hex码: 3a5f771c

从这里的讨论,特别是这个答案,这是我目前使用的function:

 private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for ( int j = 0; j < bytes.length; j++ ) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } 

我自己的微小基准(一千万字节千次,256字节千万次)表明它比任何其他替代方法快得多,大约一半时间在长arrays上。 与我从中得出的答案相比,如讨论中所build议的那样,切换到按位操作—将长arrays的时间减less了大约20%。 (编辑:当我说它比替代选项更快时,我的意思是讨论中提供的替代代码,性能等同于使用非常相似的代码的Commons Codec。

Apache Commons Codec库有一个Hex类来完成这种工作。

 import org.apache.commons.codec.binary.Hex; String foo = "I am a string"; byte[] bytes = foo.getBytes(); System.out.println( Hex.encodeHexString( bytes ) ); 

使用DatatypeConverter.printHexBinary() 。 您可以在http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/DatatypeConverter.html中阅读其文档;

例如:

 byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61}; System.out.println(javax.xml.bind.DatatypeConverter.printHexBinary(bytes)); 

将导致:

 000086003D 

正如你所看到的,这将检索代表前导零的字节数组的hexstring。

这个答案基本上是一样的问题在Java中,如何将字节数组转换为hex数字string,同时保持前导零?

最简单的解决scheme,没有外部库,没有数字常量:

 public static String byteArrayToHex(byte[] a) { StringBuilder sb = new StringBuilder(a.length * 2); for(byte b: a) sb.append(String.format("%02x", b)); return sb.toString(); } 

这个简单的oneliner为我工作
String result = new BigInteger(1, inputBytes).toString(16);
编辑 – 使用这将删除前导零,但嘿工作我的用例。 感谢@Voicu指出

番石榴解决scheme,为了完整:

 import com.google.common.io.BaseEncoding; ... byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8); final String hex = BaseEncoding.base16().lowerCase().encode(bytes); 

现在hex"48656c6c6f20776f726c64"

使用DataTypeConverter类javax.xml.bind.DataTypeConverter

String hexString = DatatypeConverter.printHexBinary(bytes[] raw);

我在这里find了三种不同的方法: http : //www.rgagnon.com/javadetails/java-0596.html

最高雅的一个,正如他也指出的,我认为是这样的:

 static final String HEXES = "0123456789ABCDEF"; public static String getHex( byte [] raw ) { if ( raw == null ) { return null; } final StringBuilder hex = new StringBuilder( 2 * raw.length ); for ( final byte b : raw ) { hex.append(HEXES.charAt((b & 0xF0) >> 4)) .append(HEXES.charAt((b & 0x0F))); } return hex.toString(); } 

存储查找表的次要代价是这个实现简单而且速度非常快。

  private static final char[] BYTE2HEX=( "000102030405060708090A0B0C0D0E0F"+ "101112131415161718191A1B1C1D1E1F"+ "202122232425262728292A2B2C2D2E2F"+ "303132333435363738393A3B3C3D3E3F"+ "404142434445464748494A4B4C4D4E4F"+ "505152535455565758595A5B5C5D5E5F"+ "606162636465666768696A6B6C6D6E6F"+ "707172737475767778797A7B7C7D7E7F"+ "808182838485868788898A8B8C8D8E8F"+ "909192939495969798999A9B9C9D9E9F"+ "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+ "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+ "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+ "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+ "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray(); ; public static String getHexString(byte[] bytes) { final int len=bytes.length; final char[] chars=new char[len<<1]; int hexIndex; int idx=0; int ofs=0; while (ofs<len) { hexIndex=(bytes[ofs++] & 0xFF)<<1; chars[idx++]=BYTE2HEX[hexIndex++]; chars[idx++]=BYTE2HEX[hexIndex]; } return new String(chars); } 

这个怎么样?

  String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } 

我会使用这样的固定长度,如哈希:

 md5sum = String.format("%032x", new BigInteger(1, md.digest())); 

我更喜欢用这个:

 final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes, int offset, int count) { char[] hexChars = new char[count * 2]; for ( int j = 0; j < count; j++ ) { int v = bytes[j+offset] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } 

接受的答案稍微灵活一些。 就我个人而言,我将所接受的答案和这个超载一起保存下来,可以在更多的上下文中使用。

我通常对debuf语句使用下面的方法,但我不知道这是否是最好的方式

 private static String 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(digits.charAt(v >> 4)); buf.append(digits.charAt(v & 0xf)); } return buf.toString(); } 

好,所以有很多方法可以做到这一点,但是如果你决定使用一个库,我会build议在你的项目中进行一些操作,看看在添加一个新的库之前,在已经是你项目的一部分的库中是否实现了一些东西只是为了做到这一点。 例如,如果你还没有

org.apache.commons.codec.binary.Hex

也许你有…

org.apache.xerces.impl.dv.util.HexBin

@maybewecouldstealavan提出的解决scheme的一个小的变体,它可以让你可视化地在输出hexstring中捆绑N个字节:

  final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); final static char BUNDLE_SEP = ' '; public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) { char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)]; for (int j = 0, k = 1; j < bytes.length; j++, k++) { int v = bytes[j] & 0xFF; int start = (j * 2) + j/bundleSize; hexChars[start] = HEX_ARRAY[v >>> 4]; hexChars[start + 1] = HEX_ARRAY[v & 0x0F]; if ((k % bundleSize) == 0) { hexChars[start + 2] = BUNDLE_SEP; } } return new String(hexChars).trim(); } 

那是:

 bytesToHexString("..DOOM..".toCharArray().getBytes(), 2); 2E2E 444F 4F4D 2E2E bytesToHexString("..DOOM..".toCharArray().getBytes(), 4); 2E2E444F 4F4D2E2E 

//转移字节更有效率//你也可以使用这个

 public static String getHexString (String s) { byte[] buf = s.getBytes(); StringBuffer sb = new StringBuffer(); for (byte b:buf) { sb.append(String.format("%x", b)); } return sb.toString(); } 

如果你正在寻找一个完全像这样的python字节数组,我已经把这个Java实现转换成python。

 class ByteArray: @classmethod def char(cls, args=[]): cls.hexArray = "0123456789ABCDEF".encode('utf-16') j = 0 length = (cls.hexArray) if j < length: v = j & 0xFF hexChars = [None, None] hexChars[j * 2] = str( cls.hexArray) + str(v) hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F) # Use if you want... #hexChars.pop() return str(hexChars) array = ByteArray() print array.char(args=[]) 
  public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; }