首页 文章

如何在Java中将字节数组转换为十六进制字符串?

提问于
浏览
526

我有一个字节数组填充十六进制数字和打印它简单的方法是非常没有意义的,因为有许多不可打印的元素 . 我需要的是以下形式的确切十六进制代码: 3a5f771c

22 回答

  • 769

    这是一个类似 java.util.Base64 的实现(部分),不是很漂亮吗?

    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=new Encoder(false);
            static final Encoder UPPER=new Encoder(true);
        }
        public static Encoder getEncoder(){
            return Encoder.LOWER;
        }
        public static Encoder getUpperEncoder(){
            return Encoder.UPPER;
        }
        //...
    }
    
  • 298

    我的解决方案是基于MaybeWeCouldStealAVan 's solution, but does not rely on any additionaly allocated lookup tables. It does not uses any ' int-to-char'演员黑客(实际上, Character.forDigit() 做了,执行一些比较以检查数字真正是什么),因此可能会慢一些 . 请随时随地使用它 . 干杯 .

    public static String bytesToHex(final byte[] bytes)
    {
        final int numBytes = bytes.length;
        final char[] container = new char[numBytes * 2];
    
        for (int i = 0; i < numBytes; i++)
        {
            final int b = bytes[i] & 0xFF;
    
            container[i * 2] = Character.forDigit(b >>> 4, 0x10);
            container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10);
        }
    
        return new String(container);
    }
    
  • 22
    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;
      }
    
  • 40

    我更喜欢用这个:

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

    它可以稍微灵活地适应已接受的答案 . 就个人而言,我同时保留了接受的答案和这种重载,可以在更多情况下使用 .

  • 14

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

    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();
    }
    
  • 14
    private static String bytesToHexString(byte[] bytes, int length) {
            if (bytes == null || length == 0) return null;
    
            StringBuilder ret = new StringBuilder(2*length);
    
            for (int i = 0 ; i < length ; i++) {
                int b;
    
                b = 0x0f & (bytes[i] >> 4);
                ret.append("0123456789abcdef".charAt(b));
    
                b = 0x0f & bytes[i];
                ret.append("0123456789abcdef".charAt(b));
            }
    
            return ret.toString();
        }
    
  • 1

    使用 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
    

    如您所见,这将检索表示带前导零的字节数组的十六进制字符串 .

    这个答案基本上与问题In Java, how do I convert a byte array to a string of hex digits while keeping leading zeros?相同

  • 347

    @maybewecouldstealavan提出的解决方案的一个小变体,它允许您在输出十六进制字符串中可视地将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
    
  • 2

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

  • 0

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

    好的,有很多方法可以做到这一点,但是如果你决定使用一个库,我会建议在你的项目中讨论是否在添加新库之前已经在已经是项目一部分的库中实现了某些东西只是这样做 . 例如,如果您还没有

    org.apache.commons.codec.binary.Hex

    也许你有......

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

  • 0

    Guava 解决方案,为了完整性:

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

    现在 hex"48656c6c6f20776f726c64" .

  • 2

    在此页面上找不到任何解决方案

    • 使用循环

    • 使用javax.xml.bind.DatatypeConverter编译正常但经常在运行时抛出java.lang.NoClassDefFoundError .

    这是一个没有上述缺陷的解决方案(没有承诺我没有其他缺陷)

    import java.math.BigInteger;
    
    import static java.lang.System.out;
    public final class App2 {
        // | proposed solution.
        public static String encode(byte[] bytes) {          
            final int length = bytes.length;
    
            // | BigInteger constructor throws if it is given an empty array.
            if (length == 0) {
                return "00";
            }
    
            final int evenLength = (int)(2 * Math.ceil(length / 2.0));
            final String format = "%0" + evenLength + "x";         
            final String result = String.format (format, new BigInteger(bytes));
    
            return result;
        }
    
        public static void main(String[] args) throws Exception {
            // 00
            out.println(encode(new byte[] {})); 
    
            // 01
            out.println(encode(new byte[] {1})); 
    
            //203040
            out.println(encode(new byte[] {0x20, 0x30, 0x40})); 
    
            // 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e
            out.println(encode("All your base are belong to us.".getBytes()));
        }
    }
    

    我无法在62个操作码下得到这个,但是如果你的第一个字节小于0x10就可以没有0填充,那么下面的解决方案只使用23个操作码 . 真的展示了如何“轻松实现自己”的解决方案,如“如果字符串长度为零则填充零”可能会变得相当昂贵,如果本机实现尚不可用(或者在这种情况下,如果BigInteger有一个选项以前缀为零)的toString) .

    public static String encode(byte[] bytes) {          
        final int length = bytes.length;
    
        // | BigInteger constructor throws if it is given an empty array.
        if (length == 0) {
            return "00";
        }
    
        return new BigInteger(bytes).toString(16);
    }
    
  • 0

    使用DataTypeConverter类 javax.xml.bind.DataTypeConverter

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

  • 8

    这个怎么样?

    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;
        }
    
  • 0

    从讨论here,特别是this回答,这是我目前使用的功能:

    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字节一千万次)显示它比任何其他替代方案快得多,大约是长阵列的一半时间 . 与我从中得到的答案相比,切换到按位运算 - 如讨论中所建议的那样 - 为长阵列削减了大约20%的时间 . (编辑:当我说它比替代品更快时,我的意思是讨论中提供的替代代码 . 性能等同于Commons Codec,它使用非常相似的代码 . )

  • 0

    以存储查找表的次要成本,这种实现简单且非常快 .

    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);
      }
    
  • 0

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

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

    我在这里发现了三种不同的方式: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();
    }
    
  • 42

    我通常使用以下方法进行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();
    }
    
  • 190

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

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

    如果你正在寻找一个与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=[])
    

相关问题