Onaltılık dökümü dizesini temsili Java kullanarak bir bayt dizisine dönüştürmek?


372

Bir bayt dizisine onaltılık değerleri temsil eden (bir döküm) uzun bir dize dönüştürmek için bir yol arıyorum.

Burada aynı soruyu yayınlayan kişiden daha iyi ifade edemezdim .

Ama orijinalliğini korumak için, kendi yolumla ifade edeceğim: varsayalım "00A0BF"ki,

byte[] {0x00,0xA0,0xBf}

ne yapmalıyım?

Ben bir Java acemi ve kullanarak BigIntegerve önde gelen hex sıfırlar için izlerken sona erdi . Ama çirkin olduğunu düşünüyorum ve basit bir şey eksik eminim.



BigInteger Burada evcilleştirildim .
John McClane

FWIW String.getBytes()düşündüğünüz gibi çalışmaz. Bunu zor yoldan öğrenmek zorunda kaldım. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
tir38

Yanıtlar:


636

İşte şimdiye kadar yayınlanan herhangi bir daha iyi olduğunu düşünüyorum bir çözüm:

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

Bunun bir gelişme olmasının nedenleri:

  • Baştaki sıfırlarla (BigInteger'den farklı olarak) ve negatif bayt değerleriyle (Byte.parseByte'den farklı) güvenli

  • Dizeyi a dönüştürmez char[]veya her bayt için StringBuilder ve String nesneleri oluşturmaz.

  • Kullanılamayabilecek kitaplık bağımlılığı yok

Argümanın assertgüvenli olduğu bilinmiyorsa, argüman kontrolü veya istisnalar eklemekten çekinmeyin .


2
Yanlış kodu çözülmüş bir örnek verebilir veya bunun nasıl yanlış olduğunu açıklayabilir misiniz?
Dave L.

5
"0" Dizesi için çalışmaz. Bir java.lang.StringIndexOutOfBoundsException
ovdsrn

49
"0" geçerli bir giriş değil. Baytların her biri iki onaltılık basamak gerektirir. Yanıtın belirttiği gibi, "Argümanın güvenli olduğu bilinmiyorsa ... argüman kontrolü eklemekten çekinmeyin."
Dave L.

12
javax.xml.bind.DatatypeConverter.parseHexBinary (hexString), mikro testlerimdeki yukarıdaki çözümden yaklaşık% 20 daha hızlı görünüyor (ne kadar küçük olursa olsun) ve geçersiz girişlere istisnalar atma (örn. "gg" geçerli bir hexString değil, önerilen çözümü kullanarak -77 değerini döndürür).
Trevor Freeman

6
@DaedalusAlpha Bağlamınıza bağlıdır, ancak genellikle bu tür şeylerle hızlı ve yüksek sesle başarısız olmanın daha iyi olduğunu düşünüyorum, böylece sessizce yanlış veri döndürmek yerine varsayımlarınızı düzeltebilirsiniz.
Dave L.

331

Tek gömlekleri:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Uyarılar :

  • Eğer java.se.ee-modülleri --add belirtmedikçe bir ClassNotFoundException neden olacaktır böylece Java 9 Jigsaw bu (varsayılan) java.se kök setinin artık parçasıdır (sayesinde @ eckes)
  • Android'de mevcut değil ( Fabiannot ettiğiniz için teşekkürler ), ancak sisteminiz herhangi bir nedenle eksikse kaynak kodunu alabilirsinizjavax.xml . @ Bert RegelinkKaynağını ayıkladığınız için teşekkürler .

14
Kısa ve beri IMHO bu kabul / üst cevap olmalıdır cleanish (Davel cevabı @ aksine) ve (skaffman yanıt gibi) herhangi bir dış kütüphanelerini gerektirmez. Ayrıca, <Bisikleti yeniden keşfetme konusunda eskimiş bir şaka girin> .
Priidu Neemre

9
datatypeconverter sınıfı örneğin android'de mevcut değildir.
Fabian

4
Uyarı: Bu (varsayılan) artık bir parçası olan Java 9 Jigsaw java.sebir neden olacaktır böylece kök seti ClassNotFoundExceptionbelirttiğiniz sürece--add-modules java.se.ee
Eckes

2
@dantebarba Bence javax.xml.bind.DatatypeConverterzaten Base64 verilerini kodlamak / kodunu çözmek için bir yöntem sağlar. Bkz parseBase64Binary()ve printBase64Binary().
DragShot

2
İle ilgili sorunlar nedeniyle eklemek için DataTypeConverterJava SE 11 tamamen JAXB API kaldırıldı ve şimdi yalnızca Java EE dahildir. Ayrıca burada önerildiği gibi bir Maven bağımlılığı olarak da ekleyebilirsiniz: stackoverflow.com/a/43574427/7347751
David Mordigal

79

Commons-codec bileşenindeki Hex sınıfı bunu sizin için yapmalıdır.

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF

6
Bu da iyi görünüyor. Bkz. Org.apache.commons.codec.binary.Hex.decodeHex ()
Dave L.

İlginçti. Ama çözümlerini takip etmekte zorlandım. Önerdiğinize göre (çift karakter sayısını kontrol etmek dışında) herhangi bir avantajı var mı?
rafraf

38

Artık kullanabilirsiniz BaseEncoding içinde guavabunu gerçekleştirmek için.

BaseEncoding.base16().decode(string);

Tersine çevirmek için kullanın

BaseEncoding.base16().encode(bytes);

27

Aslında, BigInteger'ın çözümü çok güzel olduğunu düşünüyorum:

new BigInteger("00A0BF", 16).toByteArray();

Düzenleme: Posterde belirtildiği gibi baştaki sıfırlar için güvenli değildir .


Ben de başlangıçta öyle düşündüm. Ve bunu belgelediğiniz için teşekkür ederim - Sadece yapmam gerektiğini düşünüyordum ... gerçekten anlamamış olsam da bazı garip şeyler yaptım - önde gelen 0x00'ü atlayın ve 156 baytlık bir dizede 1 bayt sırasını karıştırın ile oynuyordu.
rafraf

2
0'lara liderlik etmek için iyi bir nokta. Bayt sırasını karıştırabileceğine ve gösterildiğini görmekle ilgileneceğime emin değilim.
Dave L.

1
evet, dediğim gibi, ben de bana inanmadım :) BigInteger gelen bayt dizisi mmyers'fromHexString ve (hiçbir 0x00 ile) rahatsız edici dize karşı bir karşılaştırma koştu - onlar aynıydı. "Karışma" oldu, ama başka bir şey olabilirdi. Yarın daha yakından
bakacağım

3
BigInteger ile ilgili sorun, bir "işaret biti" olması gerektiğidir. Baştaki bayt ayarlanmış yüksek bite sahipse, sonuçtaki bayt dizisi 1. konumda fazladan 0'a sahiptir. Ama yine de +1.
Gri

25

Tek gömlekleri:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Arkasında gerçek kodu ile ilgilenen olanlar için Tek gömlekleri gelen FractalizeR , bu gelir (Ben javax.xml.bind varsayılan olarak Android () için geçerli değildir çünkü bu gerekli) com.sun.xml.internal.bind. DatatypeConverterImpl.java :

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if( len%2 != 0 )
        throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);

    byte[] out = new byte[len/2];

    for( int i=0; i<len; i+=2 ) {
        int h = hexToBin(s.charAt(i  ));
        int l = hexToBin(s.charAt(i+1));
        if( h==-1 || l==-1 )
            throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);

        out[i/2] = (byte)(h*16+l);
    }

    return out;
}

private static int hexToBin( 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 char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length*2);
    for ( byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}

3
DatatypeConverter varsayılan olarak Java 9'da bulunmaz. Tehlikeli olan kod Java 1.8 veya öncesi altında derlenecek olan koddur (daha önce kaynak ayarlarına sahip Java 9), ancak Java 9 altında "--add modules java.se.ee" olmadan bir çalışma zamanı istisnası alır.
Stephen M -on grev-

24

HexBinaryAdapterSıralamakta yeteneği arasındaki unmarshal sağlar Stringve byte[].

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public byte[] hexToBytes(String hexString) {
     HexBinaryAdapter adapter = new HexBinaryAdapter();
     byte[] bytes = adapter.unmarshal(hexString);
     return bytes;
}

Bu sadece yazdığım bir örnek ... Aslında onu olduğu gibi kullanıyorum ve kullanmak için ayrı bir yöntem yapmam gerekmiyor.


5
Yalnızca giriş dizesi (hexString) çift sayıda karakter içeriyorsa çalışır. Aksi takdirde: "main" iş parçacığındaki istisna java.lang.IllegalArgumentException: hexBinary eşit uzunlukta olmalıdır:
ovdsrn

3
Oh, bunu belirttiğin için teşekkürler. Bayt dizisi {0x00,0xA0,0xBf} olarak temsil edildiğinden, kullanıcının gerçekten tek sayıda karakteri olmamalıdır. Her baytın iki onaltılık rakamı veya kemeri vardır. Bu nedenle, herhangi bir sayıda baytın her zaman çift sayıda karakteri olmalıdır. Bundan bahsettiğiniz için teşekkürler.
GrkEngineer

8
HexBinaryAdapter kullanmak yerine doğrudan java.xml.bind.DatatypeConverter.parseHexBinary (hexString) kullanabilirsiniz (bu da DatatypeConverter'ı çağırır). Bu şekilde bir adaptör örneği nesnesi oluşturmanız gerekmez (DatatypeConverter yöntemleri statik olduğundan).
Trevor Freeman

. javax.xml.bind * Java 9'da tehlikeli şey (daha önce kaynak ayarları ile Java 9) Java 1.8 altında derlemek bu hizmeti kullanan kod veya daha önceki artık kullanılabilir, ancak bir çalışma zamanı istisnası Java 9. altında çalışan olsun
Stephen M -on grev-

15

İşte gerçekten çalışan bir yöntem (önceki yarı-doğru birkaç cevaba dayanarak):

private static byte[] fromHexString(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

Görebildiğim tek sorun giriş dizesinin çok uzun olup olmadığı; toCharArray () öğesi çağrıldığında dizenin dahili dizisinin bir kopyası oluşturulur.

EDIT: Oh, ve bu arada, bayt Java ile imzalanır, böylece giriş dizesi [0, 160, 191] yerine [0, -96, -65] dönüştürür. Ama muhtemelen bunu zaten biliyordun.


1
Teşekkürler Michael - hayat kurtarıcısın! Bir BlackBerry projesi üzerinde çalışmak ve RIM'in "Byte.parseByte (byteString, 16)" yöntemini kullanarak bir bayt dizesinin temsilini bayta geri dönüştürmeye çalışmak ... NumberFormatExcpetion atmaya devam etti. Nedenini bulmak için saatlerce yazarak harcadım "Integer.praseInt ()" öneriniz hile yaptı. Tekrar teşekkürler!!
BonanzaDriver

12

Android'de, hex ile çalışıyorsanız, okio'yu deneyebilirsiniz .

basit kullanım:

byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();

ve sonuç olacak

[-64, 0, 6, 0, 0]

Birçok farklı yöntemi test ettim ama bu en az iki kat daha hızlı!
poby

5

BigInteger()Java.math dan Yöntem çok yavaş ve recommandable değildir.

Integer.parseInt(HEXString, 16)

Rakam / Tamsayıya dönüştürülmeden bazı karakterlerde sorunlara neden olabilir

İyi Çalışan bir yöntem:

Integer.decode("0xXX") .byteValue()

İşlev:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

İyi Eğlenceler, İyi Şanslar


4

EDIT: @mmyers tarafından işaret edildiği gibi, bu yöntem, yüksek bit kümesi ("80" - "FF") bayt karşılık gelen alt dizeleri içeren giriş üzerinde çalışmaz. Açıklama şu şekildedir: Hata Kimliği: 6259307 Byte.parseByte SDK Belgelerinde tanıtıldığı gibi çalışmıyor .

public static final byte[] fromHexString(final String s) {
    byte[] arr = new byte[s.length()/2];
    for ( int start = 0; start < s.length(); start += 2 )
    {
        String thisByte = s.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    return arr;
}

1
Kapat, ancak bu yöntem verilen "00A0BBF" girişinde başarısız oluyor. Bkz. Bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307 .
Michael Myers

1
Ayrıca garip bir şekilde "9C" ile
uğraşmaz

1
@mmyers: whoa. Bu iyi değil. Karışıklık için özür dilerim. @ravigad: 9C aynı soruna sahiptir, çünkü bu durumda yüksek bit ayarlanır.
Blair Conrad

(byte) Short.parseShort (thisByte, 16) bu sorunu çözüyor
Jamey Hicks

3

Değer için, burada, birleştirme dizisine başvurmadan tek uzunluklu dizeleri destekleyen başka bir sürüm var.

public static byte[] hexStringToByteArray(String input) {
    int len = input.length();

    if (len == 0) {
        return new byte[] {};
    }

    byte[] data;
    int startIdx;
    if (len % 2 != 0) {
        data = new byte[(len / 2) + 1];
        data[0] = (byte) Character.digit(input.charAt(0), 16);
        startIdx = 1;
    } else {
        data = new byte[len / 2];
        startIdx = 0;
    }

    for (int i = startIdx; i < len; i += 2) {
        data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
                + Character.digit(input.charAt(i+1), 16));
    }
    return data;
}

2

Hep böyle bir yöntem kullandım

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

bu yöntem, boşlukla sınırlanmış onaltılık değerlere ayrılır, ancak dizeyi iki karakterden oluşan gruplara ayırmak gibi başka herhangi bir kriterde dizeyi ayırmak zor olmaz.


Dize birleştirme gereksizdir. Sadece Integer.valueOf (val, 16) kullanın.
Michael Myers

Daha önce böyle
radx

teşekkürler - garip bir şekilde bu dize ile iyi çalışır: "9C001C" veya "001C21" ve bu başarısız: "9C001C21" iş parçacığı istisna "ana" java.lang.NumberFormatException: Giriş dizesi için: "9C001C21" java.lang. NumberFormatException.forInputString (Bilinmeyen Kaynak)
rafraf

(Bu Byte/ byte
case'den

2

Character.digit çözümünü seviyorum, ama işte böyle çözdüm

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}

2

Bert Regelink tarafından sunulan Kurallar işe yaramıyor. Takip etmeyi dene:

import javax.xml.bind.DatatypeConverter;
import java.io.*;

public class Test
{  
    @Test
    public void testObjectStreams( ) throws IOException, ClassNotFoundException
    {     
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);

            String stringTest = "TEST";
            oos.writeObject( stringTest );

            oos.close();
            baos.close();

            byte[] bytes = baos.toByteArray();
            String hexString = DatatypeConverter.printHexBinary( bytes);
            byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);

            assertArrayEquals( bytes, reconvertedBytes );

            ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
            ObjectInputStream ois = new ObjectInputStream(bais);

            String readString = (String) ois.readObject();

            assertEquals( stringTest, readString);
        }
    }

2
Bu gerçekten farklı bir sorundur ve muhtemelen başka bir iş parçacığına aittir.
Sean Coffey

1

Kernel Panic'i çözümün benim için en yararlısı buldum, ancak hex dizesi tek bir sayı ise sorunla karşılaştı. şu şekilde çözdü:

boolean isOdd(int value)
{
    return (value & 0x01) !=0;
}

private int hexToByte(byte[] out, int value)
{
    String hexVal = "0123456789ABCDEF"; 
    String hexValL = "0123456789abcdef";
    String st = Integer.toHexString(value);
    int len = st.length();
    if (isOdd(len))
        {
        len+=1; // need length to be an even number.
        st = ("0" + st);  // make it an even number of chars
        }
    out[0]=(byte)(len/2);
    for (int i =0;i<len;i+=2)
    {
        int hh = hexVal.indexOf(st.charAt(i));
            if (hh == -1)  hh = hexValL.indexOf(st.charAt(i));
        int lh = hexVal.indexOf(st.charAt(i+1));
            if (lh == -1)  lh = hexValL.indexOf(st.charAt(i+1));
        out[(i/2)+1] = (byte)((hh << 4)|lh);
    }
    return (len/2)+1;
}

Bir diziye onaltılık sayılar bir dizi ekliyorum, bu yüzden ben kullanıyorum diziye referans geçmek ve int dönüştürülen ve sonraki hex numarasının göreceli konumunu döndürme gerekir. Böylece son bayt dizisi [0] altıgen çifti, [1 ...] altıgen çifti, daha sonra çift sayısı ...


1

Seçilmiş op çözümüne göre, aşağıdakiler biraz daha verimli olmalıdır:

  public static byte [] hexStringToByteArray (final String s) {
    if (s == null || (s.length () % 2) == 1)
      throw new IllegalArgumentException ();
    final char [] chars = s.toCharArray ();
    final int len = chars.length;
    final byte [] data = new byte [len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
    }
    return data;
  }

Çünkü: char dizisine ilk dönüşüm charAt'ta uzunluk kontrollerini yedekler


1

Kodlama stiliniz olarak Java 8 akışları için bir tercihiniz varsa, bu sadece JDK ilkelleri kullanılarak gerçekleştirilebilir.

String hex = "0001027f80fdfeff";

byte[] converted = IntStream.range(0, hex.length() / 2)
    .map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
    .collect(ByteArrayOutputStream::new,
             ByteArrayOutputStream::write,
             (s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
    .toByteArray();

, 0, s2.size()Eğer alıcı sakıncası yoksa toplayıcı concatenate fonksiyonunda parametreler atlanabilir IOException.


0
public static byte[] hex2ba(String sHex) throws Hex2baException {
    if (1==sHex.length()%2) {
        throw(new Hex2baException("Hex string need even number of chars"));
    }

    byte[] ba = new byte[sHex.length()/2];
    for (int i=0;i<sHex.length()/2;i++) {
        ba[i] = (Integer.decode(
                "0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
    }
    return ba;
}

0

Resmi çözümüm:

/**
 * Decodes a hexadecimally encoded binary string.
 * <p>
 * Note that this function does <em>NOT</em> convert a hexadecimal number to a
 * binary number.
 *
 * @param hex Hexadecimal representation of data.
 * @return The byte[] representation of the given data.
 * @throws NumberFormatException If the hexadecimal input string is of odd
 * length or invalid hexadecimal string.
 */
public static byte[] hex2bin(String hex) throws NumberFormatException {
    if (hex.length() % 2 > 0) {
        throw new NumberFormatException("Hexadecimal input string must have an even length.");
    }
    byte[] r = new byte[hex.length() / 2];
    for (int i = hex.length(); i > 0;) {
        r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
    }
    return r;
}

private static int digit(char ch) {
    int r = Character.digit(ch, 16);
    if (r < 0) {
        throw new NumberFormatException("Invalid hexadecimal string: " + ch);
    }
    return r;
}

Gibi mi PHP HEX2BIN () Fonksiyonu ama Java tarzında.

Misal:

String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"

0

Partiye geç kaldım, ama DaveL tarafından yukarıdaki cevabı ters eylemle bir sınıfa birleştirdim.

public final class HexString {
    private static final char[] digits = "0123456789ABCDEF".toCharArray();

    private HexString() {}

    public static final String fromBytes(final byte[] bytes) {
        final StringBuilder buf = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
            buf.append(HexString.digits[bytes[i] & 0x0f]);
        }
        return buf.toString();
    }

    public static final byte[] toByteArray(final String hexString) {
        if ((hexString.length() % 2) != 0) {
            throw new IllegalArgumentException("Input string must contain an even number of characters");
        }
        final int len = hexString.length();
        final byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}

Ve JUnit test sınıfı:

public class TestHexString {

    @Test
    public void test() {
        String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};

        for (int i = 0; i < tests.length; i++) {
            String in = tests[i];
            byte[] bytes = HexString.toByteArray(in);
            String out = HexString.fromBytes(bytes);
            System.out.println(in); //DEBUG
            System.out.println(out); //DEBUG
            Assert.assertEquals(in, out);

        }

    }

}

0

Bu çok eski bir iplik olduğunu biliyorum, ama yine de benim kuruşa değer eklemek istiyorum.

Gerçekten ikili bir dönüştürücü basit bir hex dize kodlamak gerekirse, ben aşağıdaki gibi yapmak istiyorum.

public static byte[] hexToBinary(String s){

  /*
   * skipped any input validation code
   */

  byte[] data = new byte[s.length()/2];

  for( int i=0, j=0; 
       i<s.length() && j<data.length; 
       i+=2, j++)
  {
     data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
  }

  return data;
}

0

En temiz çözüm değil. Ama benim için çalışıyor ve iyi biçimlendirilmiş:

private String createHexDump(byte[] msg, String description) {
    System.out.println();
    String result = "\n" + description;
    int currentIndex = 0;
    int printedIndex = 0;
    for(int i=0 ; i<msg.length ; i++){
        currentIndex++;
        if(i == 0){
            result += String.format("\n  %04x ", i);
        }
        if(i % 16 == 0 && i != 0){
            result += " | ";
            for(int j=(i-16) ; j<msg.length && j<i ; j++) {
                char characterToAdd = (char) msg[j];
                if (characterToAdd == '\n') {
                    characterToAdd = ' ';
                }
                result += characterToAdd;
                printedIndex++;
            }

            result += String.format("\n  %04x ", i);
        }

        result += String.format("%02x ", msg[i]);
    }

    if(currentIndex - printedIndex > 0){
        int leftOvers = currentIndex - printedIndex;
        for(int i=0 ; i<16-leftOvers ; i++){
            result += "   ";
        }

        result += " | ";

        for(int i=msg.length-leftOvers ; i<msg.length ; i++){
            char characterToAdd = (char) msg[i];
            if (characterToAdd == '\n') {
                characterToAdd = ' ';
            }
            result += characterToAdd;
        }
    }

    result += "\n";

    return result;
}

Çıktı:

  S -> C
    0000 0b 00 2e 06 4d 6f 72 69 74 7a 53 6f 6d 65 20 54  |  .Heyyy Some T
    0010 43 50 20 73 74 75 66 66 20 49 20 63 61 70 74 75  | CP stuff I captu
    0020 72 65 64 2e 2e 77 65 6c 6c 20 66 6f 72 6d 61 74  | red..well format
    0030 3f                                               | ?

-2

Bence senin için yapacak. Birlikte bir dize olarak veri döndürdü benzer bir işlevden Arnavut kaldırımı:

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

İlk olarak, dizeyi büyük harfe dönüştürmeniz gerekmez. İkincisi, karakterleri çok daha verimli olması gereken bir StringBuffer'a doğrudan eklemek mümkündür.
Michael Myers

-2

Benim için çözüm buydu, HEX = "FF01" sonra FF (255) ve 01 (01) 'e bölündü

private static byte[] BytesEncode(String encoded) {
    //System.out.println(encoded.length());
    byte result[] = new byte[encoded.length() / 2];
    char enc[] = encoded.toUpperCase().toCharArray();
    String curr = "";
    for (int i = 0; i < encoded.length(); i=i+2) {
        curr = encoded.substring(i,i+2);
        System.out.println(curr);
        if(i==0){
            result[i]=((byte) Integer.parseInt(curr, 16));
        }else{
            result[i/2]=((byte) Integer.parseInt(curr, 16));
        }

    }
    return result;
}

Bu soru bir süredir cevaplandırılmıştır ve yerinde birkaç iyi alternatif vardır; ne yazık ki, cevabınız bu noktada önemli ölçüde iyileştirilmiş bir değer sağlamıyor.
rfornal
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.