У мене є байтовий масив, наповнений шістнадцятковими номерами, і надрукувати його простий спосіб досить безглуздо, оскільки є безліч недрукованих елементів. Що мені потрібно - це точний гек-код у вигляді:3a5f771c
У мене є байтовий масив, наповнений шістнадцятковими номерами, і надрукувати його простий спосіб досить безглуздо, оскільки є безліч недрукованих елементів. Що мені потрібно - це точний гек-код у вигляді:3a5f771c
Відповіді:
З обговорення тут , і особливо цієї відповіді, це функція, яку я зараз використовую:
private static final char[] HEX_ARRAY = "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] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
Мої власні крихітні орієнтири (мільйон байт в тисячу разів, 256 байт в 10 мільйонів разів) показали, що це набагато швидше, ніж будь-яка інша альтернатива, приблизно в половину часу на довгих масивах. Порівняно з відповіддю, з якого я його взяв, перехід на побіжні операції --- як було запропоновано в дискусії --- скоротив приблизно 20% часу на довгі масиви. (Редагувати: Коли я кажу, що це швидше, ніж альтернативи, я маю на увазі альтернативний код, запропонований в дискусіях. Продуктивність еквівалентна Commons Codec, який використовує дуже схожий код.)
Версія 2k20 стосовно компактних рядків Java 9:
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}
String printHexBinary(byte[])
та byte[] parseHexBinary(String)
. printHexBinary
однак значно (2х) повільніше, ніж функція у цій відповіді. (Я перевірив джерело; він використовує stringBuilder
. parseHexBinary
Використовує масив.) Дійсно, однак, для більшості цілей це досить швидко, і ви, мабуть, вже його маєте.
printHexBinary
?
javax.xml.bind.DataTypeConverter
видаляється з Java 11.
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;
org.bouncycastle.util.encoders.Hex
допомогою цього методу:String toHexString(byte[] data)
Метод javax.xml.bind.DatatypeConverter.printHexBinary()
, що є частиною архітектури Java для прив'язки XML (JAXB) , був зручним способом перетворення a byte[]
в шістнадцяткову рядок. DatatypeConverter
Клас також включає безліч інших корисних методів даних маніпуляцій.
У Java 8 та новіших версіях JAXB входила до стандартної бібліотеки Java. Він був застарілий з Java 9 і видаляється з Java 11 , як частина зусиль , щоб перемістити всі пакети Java EE в свої бібліотеки. Це довга історія . Зараз javax.xml.bind
не існує, і якщо ви хочете використовувати JAXB, який містить DatatypeConverter
, вам потрібно буде встановити API JAXB та JAXB Runtime від Maven.
Приклад використання:
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();
}
Рішення 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()
.
HashCode.fromBytes(checksum).toString()
Цей простий oneliner працює для мене
String result = new BigInteger(1, inputBytes).toString(16);
EDIT - за допомогою цього вилучите провідні нулі, але він працював для мого використання. Дякую @Voicu за те, що вказав на це
Ось кілька загальних варіантів, упорядкованих від простого (однолінійний) до складного (величезна бібліотека). Якщо вас цікавить ефективність, дивіться мікро-орієнтири нижче.
Одне дуже просте рішення - використовувати BigInteger
шістнадцяткове представлення:
new BigInteger(1, someByteArray).toString(16)
Зауважте, що оскільки ця обробка чисел не є довільними рядками байтів, вона опустить провідні нулі - це може бути, а може і не бути тим, що ви хочете (наприклад, 000AE3
проти 0AE3
3-байтного вводу). Це також дуже повільно, приблизно в 100 разів повільніше порівняно з наступним варіантом.
Тут повнофункціональним, копіювати і pasteable фрагмент коду підтримує верхній / нижній регістр і порядок байтів . Він оптимізований для мінімізації складності пам'яті та максимізації продуктивності, а також повинен бути сумісний з усіма сучасними версіями Java (5+).
private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {
// our output size will be exactly 2x byte-array length
final char[] buffer = new char[byteArray.length * 2];
// choose lower or uppercase lookup table
final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;
int index;
for (int i = 0; i < byteArray.length; i++) {
// for little endian we count from last to first
index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;
// extract the upper 4 bit and look up char (0-A)
buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
// extract the lower 4 bit and look up char (0-A)
buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
}
return new String(buffer);
}
public static String encode(byte[] byteArray) {
return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}
Повний вихідний код з ліцензією Apache v2 та декодером можна знайти тут .
Працюючи над своїм попереднім проектом, я створив цей невеликий набір інструментів для роботи з байтами в Java. Він не має зовнішніх залежностей і сумісний з Java 7+. Він включає, серед іншого, дуже швидкий і добре перевірений HEX en / декодер:
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Ви можете перевірити це на Github: bytes-java .
Звичайно, є хороші кодеки . ( попереджуюча думка наперед ) Під час роботи над проектом, описаним вище, я проаналізував код і був дуже розчарований; багато дублікатів неорганізованого коду, застарілі та екзотичні кодеки, ймовірно, корисні лише для дуже мало і зовсім над інженерними та повільними реалізаціями популярних кодеків (зокрема Base64). Тому я б прийняв обгрунтоване рішення, якщо ви хочете скористатися ним чи альтернативою. У будь-якому випадку, якщо ви все ще хочете його використовувати, ось фрагмент коду:
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
Найчастіше у вас вже є Guava як залежність. Якщо так, просто використовуйте:
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Якщо ви використовуєте рамку Spring із Spring Security, ви можете скористатися наступним:
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
Якщо ви вже використовуєте рамку безпеки Bouncy Castle, ви можете використовувати її Hex
утиліту:
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
У попередніх версіях Java (8 і нижче) код Java для JAXB включався як залежність від часу виконання. Оскільки модулялізація Java 9 та Jigsaw, ваш код не може отримати доступ до іншого коду поза його модулем без явного декларування. Тому будьте в курсі, якщо у вас виняток:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
під час роботи на JVM з Java 9+. Якщо так, то переключіть реалізацію на будь-яку з вищезазначених альтернатив. Дивіться також це питання .
Ось результати простого мікро-орієнтиру JMH, що кодує байтові масиви різного розміру . Значення - це операції в секунду, тим вище , тим краще. Зауважте, що мікро-орієнтири дуже часто не відображають поведінку у реальному світі, тому сприймайте ці результати із зерном солі.
| Name (ops/s) | 16 byte | 32 byte | 128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger | 2,088,514 | 1,008,357 | 133,665 | 4 |
| Opt2/3: Bytes Lib | 20,423,170 | 16,049,841 | 6,685,522 | 825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 | 529 |
| Opt5: Guava | 10,177,925 | 6,937,833 | 2,094,658 | 257 |
| Opt6: Spring | 18,704,986 | 13,643,374 | 4,904,805 | 601 |
| Opt7: BC | 7,501,666 | 3,674,422 | 1,077,236 | 152 |
| Opt8: JAX-B | 13,497,736 | 8,312,834 | 2,590,940 | 346 |
Характеристики: JDK 8u202, i7-7700K, Win10, 24GB Ram. Повний тест дивіться тут .
Використовуйте клас DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Я б використав щось подібне для фіксованої довжини, як хеши:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
Тут я знайшов три різні способи: 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
ключ?
При незначних витратах на зберігання таблиці пошуку, ця реалізація проста і дуже швидка.
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);
}
BYTE2HEX
масив простим for
циклом?
static { }
блоці.
Як щодо цього?
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;
}
Я вважаю за краще використовувати це:
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);
}
Це трохи гнучкіша адаптація прийнятої відповіді. Особисто я зберігаю як прийняту відповідь, так і це перевантаження разом з нею, придатною для використання в інших контекстах.
Зазвичай я використовую наступний метод для налагодження заяви, але я не знаю, це найкращий спосіб зробити це чи ні
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);
.
Гаразд, існує маса способів зробити це, але якщо ви вирішили використовувати бібліотеку, я б запропонував задуматися у вашому проекті, щоб побачити, чи щось було реалізовано в бібліотеці, яка вже є частиною вашого проекту, перш ніж додавати нову бібліотеку просто для цього. Наприклад, якщо у вас цього ще немає
org.apache.commons.codec.binary.Hex
можливо, у вас є ...
org.apache.xerces.impl.dv.util.HexBin
Якщо ви використовуєте рамку Spring Security, ви можете використовувати:
import org.springframework.security.crypto.codec.Hex
final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
Додавання утиліти для простого функціонування - це не гарний варіант. Замість цього збирайте власні класи корисних програм. нижче можлива швидша реалізація.
public class ByteHex {
public static int hexToByte(char ch) {
if ('0' <= ch && ch <= '9') return ch - '0';
if ('A' <= ch && ch <= 'F') return ch - 'A' + 10;
if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
return -1;
}
private static final String[] byteToHexTable = new String[]
{
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
};
private static final String[] byteToHexTableLowerCase = new String[]
{
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"
};
public static String byteToHex(byte b){
return byteToHexTable[b & 0xFF];
}
public static String byteToHex(byte[] bytes){
if(bytes == null) return null;
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
return sb.toString();
}
public static String byteToHex(short[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
return sb.toString();
}
public static String byteToHexLowerCase(byte[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
return sb.toString();
}
public static byte[] hexToByte(String hexString) {
if(hexString == null) return null;
byte[] byteArray = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length(); i += 2) {
byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
}
return byteArray;
}
public static byte hexPairToByte(char ch1, char ch2) {
return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
}
}
Невеликий варіант рішення, запропонований @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);
}
Моє рішення базується на рішенні можливоWeCouldStealAVan, але не покладається на будь-які додатково виділені таблиці пошуку. Він не використовує жодних хат-кодів "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);
}
Якщо ви шукаєте байтовий масив точно такий, як цей для 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=[])
Ось така 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;
}
//...
}
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();
}
Converts bytes data to hex characters
@param bytes byte array to be converted to hex string
@return byte String in hex format
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
toHexString(...)
метод, який може допомогти, якщо це те, що ви шукаєте. ТакожString.format(...)
можна виконати кілька акуратних прийомів форматування, використовуючи%2x
рядок коду.