我有一个字节数组充满十六进制数字和打印它的简单方式是相当没有意义的,因为有许多不可打印的元素。我需要的是精确的十六进制形式:3a5f771c


当前回答

如果你想让它更具可读性,并将字节彼此分开,你可以在Java 17+中使用以下代码:

byte[] yourByteArray = { -128, 0, 127 };
String hexString = new String(HexFormat.ofDelimiter(" ").formatHex(yourByteArray));
// 80 00 7f

其他回答

javax.xml.bind.DatatypeConverter.printHexBinary()方法是用于XML绑定的Java体系结构(JAXB)的一部分,是将字节[]转换为十六进制字符串的方便方法。DatatypeConverter类还包括许多其他有用的数据操作方法。

在Java 8和更早的版本中,JAXB是Java标准库的一部分。它在Java 9中被弃用,在Java 11中被移除,这是将所有Java EE包移动到它们自己的库中的努力的一部分。说来话长。现在,javax.xml.bind还不存在,如果希望使用包含DatatypeConverter的JAXB,则需要从Maven安装JAXB API和JAXB运行时。

使用示例:

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

会导致:

000086003D

这个和这个答案是一样的。

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

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

Java 17最终包含HexFormat类,所以你可以简单地做:

HexFormat.of().formatHex(bytes);

它支持配置为小写/大写,分隔符,前缀,后缀等。

这是一个java.util。类似base64的实现,是不是很漂亮?

import java.util.Arrays;

public class Base16/* a.k.a. Hex */ {
    public static class Encoder{
        private static char[] toLowerHex={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        private static char[] toUpperHex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        private boolean upper;
        public Encoder(boolean upper) {
            this.upper=upper;
        }
        public String encode(byte[] data){
            char[] value=new char[data.length*2];
            char[] toHex=upper?toUpperHex:toLowerHex;
            for(int i=0,j=0; i<data.length; i++){
                int octet=data[i]&0xFF;
                value[j++]=toHex[octet>>4];
                value[j++]=toHex[octet&0xF];
            }
            return new String(value);
        }
        static final Encoder LOWER_CASE=new Encoder(false);
        static final Encoder UPPER_CASE=new Encoder(true);
    }
    public static Encoder getEncoder(){
        return Encoder.LOWER_CASE;
    }
    public static Encoder getUpperEncoder(){
        return Encoder.UPPER_CASE;
    }

    public static class Decoder{
      private static int maxIndex=102;
      private static int[] toIndex;
      static {
        toIndex=new int[maxIndex+1];
        Arrays.fill(toIndex, -1);
        char[] chars={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'};
        for(int i=0; i<chars.length; i++) {
          toIndex[(int)chars[i]]=i;
        }
      }
      public Decoder() {
      }
      public byte[] decode(String str) {
          char[] value=str.toCharArray();
          int start=0;
          if(value.length>2 && value[0]=='0' && (value[1]=='x' || value[1]=='X')) {
            start=2;
          }
          int byteLength=(value.length-start)/2; // ignore trailing odd char if exists
          byte[] data=new byte[byteLength];
          for(int i=start,j=0;i<value.length;i+=2,j++){
              int i1;
              int i2;
              char c1=value[i];
              char c2=value[i+1];
              if(c1>maxIndex || (i1=toIndex[(int)c1])<0 || c2>maxIndex || (i2=toIndex[(int)c2])<0) {
                throw new IllegalArgumentException("Invalid character at "+i);
              }
              data[j]=(byte)((i1<<4)+i2);
          }
          return data;
      }
      static final Decoder IGNORE_CASE=new Decoder();
  }
  public static Decoder getDecoder(){
      return Decoder.IGNORE_CASE;
  }
}

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