Невозможно преобразовать byteArray в String и reverse [duplicate]

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

519
задан Ciro Santilli 新疆改造中心 六四事件 法轮功 2 May 2015 в 19:55
поделиться

22 ответа

Используйте 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

Как вы можете видеть, это приведет к получению шестнадцатеричной строки, представляющей массив байтов с ведущими нулями.

Этот ответ в основном такой же, как в вопросе . В Java, как мне преобразовать массив байтов в строку шестнадцатеричных цифр, сохраняя ведущие нули?

740
ответ дан Community 19 August 2018 в 08:38
поделиться
  • 1
    Я только что нашел javax.xml.bind.DataTypeConverter , часть стандартного дистрибутива. Почему это не возникает, когда вы сталкиваетесь с такой проблемой в Google? Много полезных инструментов, в том числе String printHexBinary(byte[]) и byte[] parseHexBinary(String). printHexBinary, однако, намного (2x) медленнее, чем функция в этом ответе. (Я проверил источник, он использует stringBuilder. parseHexBinary использует массив.) Действительно, для большинства целей это достаточно быстро, и вы, вероятно, уже имеете его. – maybeWeCouldStealAVan 31 March 2012 в 02:31
  • 2
    +1 для ответа, так как у Android нет DataTypeConverter – Vaiden 29 May 2013 в 11:49
  • 3
    @maybeWeCouldStealAVan: JDK 7 теперь с открытым исходным кодом. Мы должны представить патч для повышения производительности для printHexBinary? – kevinarpe 10 July 2013 в 18:05
  • 4
    @maybeWeCouldStealAVan не могли бы вы объяснить, как это работает. Я следую по большей части, но мне очень нравится понимать, что происходит при использовании кода. Благодаря! – jjNford 12 July 2013 в 20:08
  • 5
    @ bpbhat77 Для обратного просмотра см. stackoverflow.com/a/140861/1284661 – maybeWeCouldStealAVan 21 April 2014 в 11:18
  • 6
    Хорошее решение, хотя, к сожалению, не одно, что действительно в Android. – Kazriko 2 July 2014 в 01:28
  • 7
    @ Kazriko, возможно, вы хотите прочитать code.google.com/p/dalvik/wiki/JavaxPackages . Это способ получить классы javax в Android. Но если вы хотите только преобразовать в hex, это не стоит проблем. – PhoneixS 2 July 2014 в 08:24
  • 8
    DatatypeConverter больше не доступен по состоянию на JDK 9 – pmcollins 8 October 2017 в 21:24
  • 9
    @PhoneixS Он по-прежнему существует, но не является частью среды выполнения по умолчанию (из-за модулей Java 9). – Spotlight 16 December 2017 в 07:02
  • 10
    не полагайтесь на javax.xml.bind, он компилируется отлично, но не может быть найден во время выполнения. если да, будьте готовы обращаться с java.lang.NoClassDefFoundError – Dmitry 14 May 2018 в 22:50
755
ответ дан Community 30 October 2018 в 21:01
поделиться

Хорошо, поэтому есть несколько способов сделать это, но если вы решите использовать библиотеку, я предлагаю заглянуть в ваш проект, чтобы увидеть, было ли что-то реализовано в библиотеке, которая уже является частью вашего проекта, перед добавлением это новая библиотека. Например, если у вас еще нет

org.apache.commons.codec.binary.Hex

, возможно, у вас есть ...

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

2
ответ дан Aaron Cooley 19 August 2018 в 08:38
поделиться

Я предпочитаю использовать это:

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

Это немного более гибкая адаптация принятого ответа. Лично я сохраняю как принятый ответ, так и эту перегрузку вместе с ним, можно использовать в других контекстах.

2
ответ дан Bamaco 19 August 2018 в 08:38
поделиться
  • 1
    Первоначальный вопрос был для байта [] для String. Посмотрите hex в байты [] или задайте другой вопрос, @NonExistent. – Bamaco 25 August 2014 в 14:46

// Сдвиг байтов более эффективен // Вы можете использовать этот тоже

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();
}
0
ответ дан BluePurse 19 August 2018 в 08:38
поделиться

Небольшой вариант решения, предложенный @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
1
ответ дан Campa 19 August 2018 в 08:38
поделиться

Невозможно найти решение на этой странице, которое не работает

  1. Использовать цикл
  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 кодами операций, но если вы можете жить без 0 дополнений, если первый байт меньше 0x10, тогда следующее решение использует только 23 кода операций. На самом деле показывает, как «простые для реализации» решения, такие как «pad с нулевым значением, если длина строки нечетна», могут стать довольно дорогими, если собственная реализация еще не доступна (или в этом случае, если 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);
}
1
ответ дан Dmitry 19 August 2018 в 08:38
поделиться

Этот простой oneliner работает для меня String result = new BigInteger(1, inputBytes).toString(16); EDIT - с помощью этого удаляются ведущие нули, но эй работал на мой случай использования. Спасибо @Voicu за указание на это

37
ответ дан everconfusedGuy 19 August 2018 в 08:38
поделиться

Использовать класс DataTypeConverter javax.xml.bind.DataTypeConverter

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

20
ответ дан feeling unwelcome 19 August 2018 в 08:38
поделиться

Здесь 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;
    }
    //...
}
0
ответ дан fuweichin 19 August 2018 в 08:38
поделиться

Если вы ищете массив байтов, подобный этому для 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=[])
0
ответ дан helencrump 19 August 2018 в 08:38
поделиться

При незначительной стоимости хранения таблицы поиска эта реализация проста и очень быстра.

 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);
  }
13
ответ дан higginse 19 August 2018 в 08:38
поделиться
  • 1
    Почему бы не инициализировать массив BYTE2HEX простым циклом for? – icza 18 July 2014 в 11:07
  • 2
    @icza Это возможно даже при статическом финальном (aka constant) поле? – nevelis 6 July 2018 в 20:44
  • 3
    @nevelis Он может быть назначен в блоке static { }. – マルちゃん だよ 13 July 2018 в 06:26

Как насчет этого?

    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;
    }
7
ответ дан JoseM 19 August 2018 в 08:38
поделиться
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();
    }
0
ответ дан kakopappa 19 August 2018 в 08:38
поделиться

Я обычно использую следующий метод для инструкции 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();
}
2
ответ дан lucky1928 19 August 2018 в 08:38
поделиться
  • 1
    Если ваш дебаффер имеет плохой день, попробуйте создать экземпляр StringBuilder с несколькими символами для поддержки: StringBuilder buf = new StringBuilder(data.length * 2);. – greybeard 13 February 2016 в 19:27

Я нашел здесь три разных способа: 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();
}
13
ответ дан Michael Bisbjerg 19 August 2018 в 08:38
поделиться
  • 1
    Другие методы выполнялись на моем 64-байтовом образце в 5 мс, это работает в 0 мс. Вероятно, лучше всего из-за отсутствия каких-либо других строковых функций, таких как формат. – Joseph Lust 10 May 2013 в 03:58
  • 2
    if (raw == null) return null не работает быстро. Зачем вам когда-либо использовать ключ null? – Maarten Bodewes 26 February 2014 в 22:50
  • 3
    Я полагаю, что это привычка вводить подтверждение. В этом случае мы предотвращаем любое исключение ссылки Null и оставляем его вызывающей стороне для обработки плохих данных. – Michael Bisbjerg 27 February 2014 в 23:10

Мое решение основано на решении MaybeWeCouldStealAVan, но не полагается на какие-либо дополнительные распределенные таблицы поиска. Он не использует какие-либо хакеры «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);
}
0
ответ дан Netherwire 19 August 2018 в 08:38
поделиться

Простейшее решение, без внешних библиотек, без цифр:

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();
}
182
ответ дан Pointer Null 19 August 2018 в 08:38
поделиться
  • 1
    Это очень медленно, в среднем в 1000 раз медленнее (на 162 байта), чем в верхнем ответе. Избегайте использования String.Format, если производительность имеет значение. – pt123 9 June 2013 в 03:51
  • 2
    Может быть, медленно. Это хорошо для вещей, происходящих изредка, таких как логин или аналогичный. – Pointer Null 13 June 2013 в 21:00
  • 3
    Если это медленно, ну и что? В моем случае использования это просто для отладочной инструкции, поэтому спасибо за этот фрагмент кода. – vikingsteve 18 November 2013 в 21:08
  • 4
    Повторное использование библиотеки путем включения дополнительных файлов JAR в несколько десятков килобайт будет не совсем эффективным, если вам нужна эта функция (на некоторых платформах, таких как Android, весь Jar включен в конечное приложение). И иногда более короткий и более четкий код лучше, когда производительность не нужна. – personne3000 8 May 2014 в 15:28
  • 5
    @ personne3000, возможно, но в этом случае вам нужна поддержка потоков, а не одна функция вызова. это легко понять и запомнить, а следовательно, и поддерживать. – Maarten Bodewes 12 June 2014 в 18:35

Решение 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".

41
ответ дан Stephan202 19 August 2018 в 08:38
поделиться
  • 1
    В Guava вы также можете использовать new HashCode(bytes).toString(). – mfulton26 3 July 2017 в 18:48
  • 2
    По Гува 22.0 это HashCode.fromBytes(checksum).toString() – Devstr 2 March 2018 в 16:55

Библиотека 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 ) );
329
ответ дан Tim Castelijns 19 August 2018 в 08:38
поделиться
  • 1
    @cytinus - My downvote произошел 4 месяца назад, поэтому я не совсем уверен в том, что я думал, но я, вероятно, возражал против размера библиотеки. Это небольшая функция внутри программы; нет необходимости добавлять такую ​​громоздкую библиотеку в проект для ее выполнения. – ArtOfWarfare 30 March 2013 в 07:19
  • 2
    @ArtOfWarefare Я согласен, поэтому вместо import org.apache.commons.codec.*; вы можете сделать import org.apache.commons.codec.binary.Hex; – cytinus 13 April 2013 в 00:49
  • 3
    @ArtOfWarfare Я должен не согласиться. Единственное, что ужасно, это то, что библиотеки сообщества apache по умолчанию не включены в JRE и JDK. Есть несколько библиотек, которые настолько полезны, что по умолчанию они действительно должны быть в вашем классе, и это один из них. – corsiKa 21 August 2013 в 16:36
  • 4
    Я настоятельно рекомендую, чтобы этот ответ был заменен как лучший ответ. Всегда голосуйте за использование хорошо протестированной, совершенной, открытой исходной библиотеки по специальному коду, который не улучшается. – Dmitriy Likhten 26 February 2014 в 20:53
  • 5
    Или, если вы используете BouncyCastle ( org.bouncycastle: bcprov-jdk15on ), вы можете использовать этот класс: org.bouncycastle.util.encoders.Hex с помощью этого метода: String toHexString(byte[] data) – Guillaume Husta 30 March 2017 в 09:18

Я использовал бы что-то вроде этого для фиксированной длины, например хэши:

md5sum = String.format("%032x", new BigInteger(1, md.digest()));
8
ответ дан Usagi Miyamoto 19 August 2018 в 08:38
поделиться
  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;
  } 
0
ответ дан 田咖啡 19 August 2018 в 08:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: