Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Используйте 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, как мне преобразовать массив байтов в строку шестнадцатеричных цифр, сохраняя ведущие нули?
Хорошо, поэтому есть несколько способов сделать это, но если вы решите использовать библиотеку, я предлагаю заглянуть в ваш проект, чтобы увидеть, было ли что-то реализовано в библиотеке, которая уже является частью вашего проекта, перед добавлением это новая библиотека. Например, если у вас еще нет
org.apache.commons.codec.binary.Hex
blockquote>, возможно, у вас есть ...
org.apache.xerces.impl.dv.util.HexBin
blockquote>
Я предпочитаю использовать это:
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);
}
Это немного более гибкая адаптация принятого ответа. Лично я сохраняю как принятый ответ, так и эту перегрузку вместе с ним, можно использовать в других контекстах.
// Сдвиг байтов более эффективен // Вы можете использовать этот тоже
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();
}
Небольшой вариант решения, предложенный @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
Невозможно найти решение на этой странице, которое не работает
Вот решение, которое не имеет недостатков выше (никаких обещаний у меня нет других недостатков)
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);
}
Этот простой oneliner работает для меня String result = new BigInteger(1, inputBytes).toString(16);
EDIT - с помощью этого удаляются ведущие нули, но эй работал на мой случай использования. Спасибо @Voicu за указание на это
Использовать класс DataTypeConverter javax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Здесь 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;
}
//...
}
Если вы ищете массив байтов, подобный этому для 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=[])
При незначительной стоимости хранения таблицы поиска эта реализация проста и очень быстра.
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;
}
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();
}
Я обычно использую следующий метод для инструкции 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();
}
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();
}
if (raw == null) return null
не работает быстро. Зачем вам когда-либо использовать ключ null
?
– Maarten Bodewes
26 February 2014 в 22:50
Мое решение основано на решении 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);
}
Простейшее решение, без внешних библиотек, без цифр:
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();
}
Решение 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"
.
new HashCode(bytes).toString()
.
– mfulton26
3 July 2017 в 18:48
Библиотека 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 ) );
import org.apache.commons.codec.*;
вы можете сделать import org.apache.commons.codec.binary.Hex;
– cytinus
13 April 2013 в 00:49
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()));
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;
}
String printHexBinary(byte[])
иbyte[] parseHexBinary(String)
.printHexBinary
, однако, намного (2x) медленнее, чем функция в этом ответе. (Я проверил источник, он используетstringBuilder
.parseHexBinary
использует массив.) Действительно, для большинства целей это достаточно быстро, и вы, вероятно, уже имеете его. – maybeWeCouldStealAVan 31 March 2012 в 02:31printHexBinary
? – kevinarpe 10 July 2013 в 18:05