Bir bayt dizisini Java'da onaltılık bir dizeye nasıl dönüştürebilirim?


649

Ben onaltılık sayılarla dolu bir bayt dizisi var ve birçok yazdırılamaz öğeleri olduğundan kolay yolu oldukça anlamsız baskı. Ne ihtiyacım tam hexcode şeklinde:3a5f771c


12
Neden sadece denemek ve neye sahip olduğunuzu bize göstermek değil. Kaybedecek ve kazanacak bir şeyin yok. Tamsayı, toHexString(...)aradığınız şey buysa yardımcı olabilecek bir yöntemi vardır. Ayrıca kod dizesini String.format(...)kullanarak bazı düzgün biçimlendirme hileleri yapabilirsiniz %2x.
Hovercraft Eels ile Dolu


"İhtiyacım olan şey tam altıgen şeklinde: 3a5f771c ..." - kesin bir form istediniz, ancak tam bir örnek vermediniz. Sağladığınız işleme devam ederek, ilk dört baytı bir dizeye dönüştürün ve ardından elipsleri dizeye birleştirin.
jww

1
Java 8'deki akış yardımı ile şu şekilde uygulanabilir: static String byteArrayToHex (byte [] a) {return IntStream.range (0, a.length) .mapToObj (i -> String.format ("% 02x ", a [i])). indirgemek ((acc, v) -> acc +" "+ v) .get (); }
tibetty

Yanıtlar:


901

Buradaki tartışmadan ve özellikle bu cevaptan, şu anda kullandığım işlev budur:

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

Kendi küçük ölçütlerim (bir bin bayt, bin kez, 256 bayt, 10 milyon kez), diğer dizilerden çok daha hızlı olduğunu, uzun dizilerin yaklaşık yarısında olduğunu gösterdi. Aldığım cevaba kıyasla, tartışmada önerildiği gibi bitsel ops'a geçiş - uzun diziler için zamanın yaklaşık% 20'sini kesti. (Düzenle: Alternatiflerden daha hızlı olduğunu söylediğimde, tartışmalarda sunulan alternatif kodu kastediyorum. Performans, çok benzer kod kullanan Commons Codec'e eşdeğerdir.)

Java 9 kompakt dizeleriyle ilgili 2k20 sürümü:

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

266
Standart dağıtımın bir parçası olan javax.xml.bind.DataTypeConverter'ı buldum . Google'a bu tür bir sorun çıktığında neden ortaya çıkmıyor? Birçok dahil yararlı araçlar, String printHexBinary(byte[])ve byte[] parseHexBinary(String). printHexBinaryancak, bu yanıttaki işlevden çok (2x) daha yavaştır. ; (Bir kullanır Kaynağını kontrol stringBuilder. parseHexBinaryGerçekten, olsa da, çoğu amaç için yeterince hızlı olduğunu ve muhtemelen zaten sahip bir dizi kullanır.).
Mayıs

75
Android'de DataTypeConverter olmadığından yanıt için +1
Vaiden

7
@maybeWeCouldStealAVan: JDK 7 artık açık kaynak kodlu. İçin performansı artırmak için bir yama sunmalıyız printHexBinary?
kevinarpe

3
@maybeWeCouldStealAVan lütfen bunun nasıl çalıştığını açıklayabilir misiniz? Çoğunlukla takip ediyorum ama kodu kullanırken neler olduğunu anlamaktan çok hoşlanıyorum. Teşekkürler!
jjNford

24
javax.xml.bind.DataTypeConverterJava 11'den kaldırılıyor.
The Impaler

421

Apache Commons Codec kütüphanesi vardır Hex işin sadece bu tür yapmak için sınıf.

import org.apache.commons.codec.binary.Hex;

String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );

12
@cytinus - Downvote'um 4 ay önce gerçekleşti, bu yüzden düşündüğümden tam olarak emin değilim, ama muhtemelen kütüphanenin boyutuna itiraz ediyordum. Bu program içinde küçük bir işlevdir; gerçekleştirmek için projeye böyle hantal bir kütüphane eklemeye gerek yoktur.
ArtOfWarfare

6
@ArtOfWarefare katılıyorum, yerine import org.apache.commons.codec.*;bunu yapabilirsinimport org.apache.commons.codec.binary.Hex;
cytinus

12
@ ARTOfWarfare Katılmam gerekiyor. Tek korkunç şey, apache commons kütüphanelerinin JRE ve JDK'ya varsayılan olarak dahil edilmemesidir. Varsayılan olarak sınıf yolunuzda olması gereken çok yararlı olan bazı kütüphaneler vardır ve bu da bunlardan biridir.
corsiKa

29
Bu cevabın en iyi cevap olarak değiştirilmesini şiddetle tavsiye ederim. Her zaman üzerinde test edilmemiş özel kodlar üzerinde iyi test edilmiş, performans sergileyen, açık kaynaklı bir kitaplık kullanmak için oy kullanın.
Dmitriy Likhten

6
Veya BouncyCastle ( org.bouncycastle: bcprov-jdk15on ) kullanıyorsanız, bu sınıfı kullanabilirsiniz:, org.bouncycastle.util.encoders.Hexbu yöntemle:String toHexString(byte[] data)
Guillaume Husta

320

Yöntem javax.xml.bind.DatatypeConverter.printHexBinary(), XML Bağlama için Java Mimarisi'nin (JAXB) bir parçası olan, byte[]bir hex dizesine dönüştürmenin uygun bir yoluydu . DatatypeConverterSınıf bir çok başka yararlı veri manipülasyon yöntemlerini içermektedir.

Java 8 ve önceki sürümlerinde JAXB, Java standart kitaplığının bir parçasıydı. Bu edilmiş kaldırılmış Java 9 ile ve kaldırıldı Java 11 ile kendi kütüphanelerindeki içine tüm Java EE paketlerini taşımak için bir çabanın parçası olarak,. Uzun bir hikaye . Şimdi, javax.xml.bindmevcut değil ve içeren JAXB'yi kullanmak istiyorsanız DatatypeConverter, JAXB API'sını ve JAXB Çalışma Zamanı'nı yüklemeniz gerekir .

Örnek kullanım:

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

Sonuçlanacak:

000086003D

Bu cevap aynı bu bir .


13
Ne yazık ki Android'de geçerli olan iyi bir çözüm değil.
Kazriko

@Kazriko belki code.google.com/p/dalvik/wiki/JavaxPackages okumak istersiniz . Javax sınıflarını Android'e aktarmanın bir yoludur. Ama sadece hex'e dönüştürmek istiyorsanız, sorun değil.
PhoneixS


3
@PhoneixS Hala orada, ancak varsayılan çalışma zamanının bir parçası değil (Java 9 modülleri nedeniyle).
Spotlight

2
javax.xml.bind'e güvenmeyin, iyi derler, ancak çalışma zamanında bulunamaz. yaparsanız, java.lang.NoClassDefFoundError
Dmitry

227

En basit çözüm, harici kütük yok, basamak sabitleri yok:

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
Bu çok yavaştır, üst tepkiden ortalama 1000 kat daha yavaştır (162 bayt uzunluğunda). Performans önemliyse String.Format kullanmaktan kaçının.
pt123

8
Belki yavaş. Giriş veya benzeri gibi ara sıra gerçekleşen şeyler için iyidir.
Pointer Null

29
Yavaşsa, ne olacak? Benim kullanım durumumda sadece bir hata ayıklama deyimi için, bu nedenle bu kod parçası için teşekkürler.
vikingsteve

8
İhtiyacınız olan tek şey bu işlevse (Android gibi bazı platformlarda, tüm Jar son uygulamaya dahil edilir), birkaç düzine kB'den fazladan bir JAR dosyası ekleyerek bir kütüphaneyi yeniden kullanmak tam olarak etkili olmaz. Ve bazen performansa ihtiyaç duyulmadığında daha kısa ve daha net kod daha iyidir.
personne3000

2
@ personne3000 olabilir, ancak bu durumda tek bir çağrı özelliğine değil, akış desteğine ihtiyacınız vardır. bunun anlaşılması ve hatırlanması ve dolayısıyla bakımı kolaydır.
Maarten Bodewes

59

Tamlık için bir Guava çözümü:

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

Şimdi hexise "48656c6c6f20776f726c64".


Guava'da da kullanabilirsiniz new HashCode(bytes).toString().
mfulton26

1
Guava 22.0 itibariyleHashCode.fromBytes(checksum).toString()
Devstr

43

Bu basit oneliner benim için çalışıyor
String result = new BigInteger(1, inputBytes).toString(16);
EDIT - Bunu kullanmak sıfırları kaldıracak, ama hey kullanım durumum için çalıştı. İşaret ettiğin için teşekkürler @Voicu


56
Bu oneliner önde gelen sıfır bayt bırakır.
Voicu

@Voicu ... Ve% 50 önde gelen sıfır ekleyecektir.
Maarten Bodewes

27

Basit (tek astarlı) ve karmaşık (büyük kütüphane) arasında sıralanan bazı yaygın seçenekler şunlardır. Performansla ilgileniyorsanız, aşağıdaki mikro kriterlere bakın.

Seçenek 1: Kod snippet'i - Basit

Çok basit bir çözüm, BigInteger'ın hex temsilini kullanmaktır:

new BigInteger(1, someByteArray).toString(16)

Bu, rasgele bayt dizeleri olmayan sayıları işlediğinden , baştaki sıfırları atlayacağına dikkat edin - bu, istediğiniz gibi olabilir veya olmayabilir (örneğin , 3 baytlık bir giriş için vs ). Bu da çok yavaş, yaklaşık 100x daha yavaş000AE30AE3 sonraki seçeneğe göre .

2. Seçenek: Kod snippet'i - Gelişmiş

Burada, bir tam özellikli kopya edilir ve pasteable kodu destekleyen snippet'ine üst / küçük harf ve endianness'ın . Bellek karmaşıklığını en aza indirecek ve performansı en üst düzeye çıkaracak şekilde optimize edilmiştir ve tüm modern Java sürümleriyle (5+) uyumlu olmalıdır.

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 lisansı ve kod çözücüye sahip tam kaynak kodu burada bulunabilir .

3. Seçenek: Küçük bir optimize edilmiş kitaplık kullanma: bytes-java

Önceki projem üzerinde çalışırken, Java'daki baytlarla çalışmak için bu küçük araç setini oluşturdum. Harici bir bağımlılığı yoktur ve Java 7+ ile uyumludur. Diğerlerinin yanı sıra çok hızlı ve iyi test edilmiş bir HEX en / dekoder içerir:

import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()

Github'da kontrol edebilirsiniz : bytes-java .

Seçenek 4: Apache Commons Codec Bileşeni

Tabii ki iyi 'ol commons codec bileşenleri var . ( uyarı uyarısı ) Yukarıda özetlenen proje üzerinde çalışırken kodu analiz ettim ve oldukça hayal kırıklığına uğradım; bir çok yinelenmemiş örgütlenmemiş kod, eski ve egzotik kodekler muhtemelen popüler kodeklerin (özellikle Base64) çok az ve oldukça mühendis ve yavaş uygulamaları için yararlıdır. Bu nedenle, onu kullanmak ya da bir alternatif kullanmak istiyorsanız bilinçli bir karar verirdim. Her neyse, hala kullanmak istiyorsanız, bir kod snippet'i:

import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));

5. Seçenek: Google Guava

Çoğu zaman Guava'ya bağımlılık olarak sahip değilsiniz . Öyleyse sadece kullanın:

import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);

Seçenek 6: Yay Güvenliği

Eğer kullanırsanız Bahar çerçeve ile Bahar Güvenlik aşağıdakileri kullanabilirsiniz:

import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));

Seçenek 7: Yaşam Dolu Kale

Zaten Bouncy Castle güvenlik çerçevesini kullanıyorsanız, onun Hexutil kullanabilirsiniz :

import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);

Gerçekten Seçenek 8: Java 9+ Uyumluluğu veya 'JAXBs Kullanmayın javax / xml / bind / DatatypeConverter'

Önceki Java (8 ve altı) sürümlerinde JAXB için Java kodu çalışma zamanı bağımlılığı olarak dahil edilmiştir. Java 9 ve Jigsaw modülerizasyonu nedeniyle , kodunuz açık bir bildirim olmadan modülünün dışındaki diğer koda erişemez. Bu nedenle, aşağıdaki gibi bir istisna alırsanız unutmayın:

java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

Java 9+ ile bir JVM üzerinde çalışırken. Öyleyse, uygulamaları yukarıdaki alternatiflerden herhangi birine geçirin. Ayrıca bu soruya bakın .


Mikro Deneyler

Farklı boyutlardaki bayt dizilerini kodlayan basit bir JMH mikro karşılaştırmalı değerlendirmesinin sonuçları . Değerler saniyedeki işlemlerdir, dolayısıyla daha yüksek daha iyidir. Mikro kriterlerin sıklıkla gerçek dünya davranışını temsil etmediğini unutmayın, bu nedenle bu sonuçları bir tuz tanesi ile alın.

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

Özellikler: JDK 8u202, i7-7700K, Win10, 24GB Ram. Tüm karşılaştırmalı değerlendirmeyi buradan görebilirsiniz .



21

Karma uzunluklar için böyle bir şey kullanırdım, karma gibi:

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

2
Teşekkür ederim, bu çok özlü ve uygun.
Deepan Prabhu Babu

17

Burada üç farklı yol buldum: http://www.rgagnon.com/javadetails/java-0596.html

En zarif olanı, ayrıca belirttiği gibi, bence bu:

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

Diğer yöntemler 5ms içinde benim 64 bayt örnek üzerinde çalışan, bu 0ms içinde çalışır. Muhtemelen format gibi diğer String fonksiyonlarının olmaması için en iyisidir.
Joseph Lust

if (raw == null) return nullhızlı başarısız değil. Neden hiç nullanahtar kullanasýn ?
Maarten Bodewes

Sanırım validate girmek bir alışkanlık. Bu durumda, herhangi bir Null referans istisnasını önleriz ve hatalı verileri işlemek için arayana bırakırız.
Michael Bisbjerg

16

Arama tablosunu depolamanın küçük maliyetiyle bu uygulama basit ve çok hızlıdır.

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

6
BYTE2HEXDiziyi neden basit bir fordöngü ile başlatmıyorsunuz?
icza

@icza Statik bir son (sabit olarak da bilinir) alanla bile mümkün mü?
nevelis

1
@nevelis Bir static { }blok halinde atanabilir .

1
@icza çünkü arama tablosunu oluşturmaktan daha hızlı kodlamak. Burada bellek karmaşıklığı zaman karmaşıklığı ile işlem görmektedir. daha fazla belleğe ama daha hızlı (her iki uçta da biraz daha fazla)
Patrick Favre

8

Buna ne dersin?

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

3

Herhangi bir harici kütüphane kullanmamıza veya döngülere ve sabitlere dayalı kod yazmamıza gerek yoktur.
Sadece bu yeterli:

byte[] theValue = .....
String hexaString = new BigInteger(1, theValue).toString(16);

1
Bu, everconfusedGuy'un Cevabına çok benzer.
Scratte

2

Bunu kullanmayı tercih ediyorum:

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

Kabul edilen cevabın biraz daha esnek bir uyarlamasıdır. Şahsen, hem kabul edilen cevabı hem de bu aşırı yüklenmeyi daha fazla bağlamda kullanılabilir tutuyorum.


Asıl soru Dize byte [] içindi. Onaltılık bayt'a [] bakın veya farklı bir soru sorun, @NonExistent.
Bamaco

2

Genellikle debuf deyimi için aşağıdaki yöntemi kullanın, ancak bunu yapmanın en iyi yolu olup olmadığını bilmiyorum

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
Senin Çapak kötü bir gün varsa, destek karakter bir dizi StringBuilder örnekleme içinde cluing deneyin: StringBuilder buf = new StringBuilder(data.length * 2);.
greybeard

2

Tamam, bunu yapmanın bir sürü yolu var, ancak bir kütüphane kullanmaya karar verirseniz, yeni bir kütüphane eklemeden önce projenizin bir parçası olan bir kütüphaneye bir şey uygulanıp uygulanmadığını görmek için projenizde konuşmayı öneririm. sadece bunu yapmak için. Örneğin, henüz sahip değilseniz

org.apache.commons.codec.binary.Hex

belki sende var ...

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


2

Spring Security çerçevesini kullanıyorsanız şunları kullanabilirsiniz:

import org.springframework.security.crypto.codec.Hex

final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));

2

Basit işlev için bir yarar kavanozu eklemek iyi bir seçenek değildir. Bunun yerine kendi yardımcı sınıflarınızı birleştirin. daha hızlı uygulama mümkündür.

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


}

1

@Maybewecouldstealavan tarafından önerilen, N baytlarını çıktı hex dizesinde görsel olarak bir araya getirmenize olanak tanıyan küçük bir çözüm çeşidi:

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

Yani:

bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E

bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E

1

Bu sayfada bulunmayan bir çözüm bulunamıyor

  1. Döngü kullanma
  2. İyi derleyen ancak genellikle çalışma zamanında java.lang.NoClassDefFoundError atar javax.xml.bind.DatatypeConverter kullanın.

İşte yukarıdaki kusurları olmayan bir çözüm (benimkinin başka kusurları olmadığına dair hiçbir söz yok)

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

Bunu 62 opcode altında alamadım, ancak ilk baytın 0x10'dan küçük olması durumunda 0 dolgu olmadan yaşayabiliyorsanız, aşağıdaki çözüm sadece 23 opcodes kullanır. Gerçekten yerel bir uygulama mevcut değilse (veya bu durumda, BigInteger içinde sıfırlarla ön ek yapma seçeneği varsa, "kendiniz uygulamak kolay" gibi bir çözüm "dize uzunluğu tek ise sıfırla ped" oldukça pahalı olabilir gösterir. 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

Benim çözümüm belkiWeCouldStealAVan'ın çözümüne dayanır, ancak ek olarak ayrılmış arama tablolarına dayanmaz. 'Char-to-char' hileleri kullanmaz (aslında, Character.forDigit()rakamın gerçekte ne olduğunu kontrol etmek için biraz karşılaştırma yapar) ve bu nedenle biraz daha yavaş olabilir. Lütfen istediğiniz yerde kullanmaktan çekinmeyin. Şerefe.

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

// Baytları değiştirmek daha verimlidir // Bunu da kullanabilirsiniz

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

Python için tam olarak böyle bir bayt dizisi arıyorsanız, bu Java uygulamasını python'a dönüştürdüm.

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

İşte benzer bir java.util.Base64uygulama (kısmi), güzel değil mi?

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
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
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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.