Java'da bir bayt dizisini nasıl başlatırım?


138

Java bayt dizi formunda bazı sabit değerleri (UUID) depolamak zorunda ve bu statik dizileri başlatmak için en iyi yolu ne olacağını merak ediyorum. Şu anda böyle yapıyorum, ama daha iyi bir yol olmalı gibi hissediyorum.

private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0,
    0x20, (byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b,
    0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
    0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00,
    0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c,
    (byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08,
    0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
...
and so on

Kullanabileceğim, daha az verimli olabilecek, ancak daha temiz görünecek bir şey var mı? Örneğin:

private static final byte[] CDRIVES =
    new byte[] { "0xe04fd020ea3a6910a2d808002b30309d" };

Yanıtlar:


111

Bir hexa dizesini dönüştüren bir işlev kullanarak byte[],

byte[] CDRIVES = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309d");

Java kullanarak bir bayt dizisine bir hex dökümü bir dize temsilini dönüştürme bölümünde Dave L tarafından tanımlanan işlevi kullanmanızı öneririm ?

Maksimum okunabilirlik için buraya yerleştiriyorum:

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

CDRIVES staticve öğelerine izin verirseniz final, performans düşüşü önemsizdir.


78
byte[] myvar = "Any String you want".getBytes();

Dize değişmezleri herhangi bir karakter sağlamak için kaçabilir:

byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();

50
Dize dönmediğini "0000"için {0x30,0x30,0x30,0x30}yerine (ASCII) {0x00,0x00,0x00,0x00}verenin arzu edildiği gibi (ikili)?
jww

5
Sorunun başlığına bakın. Sonra bu cevaba tekrar bakın. Şimdi söyle bana, bunun nesi yanlış? Posterin özel sorununu çözmeyebilir, ama kesinlikle benimkini çözdü. Bir pseudorandom sayı üreteci için bir tohum olarak kullanmak için bir bayt dizisine bir dize dönüştürmek gerekiyordu ve bu bir cazibe gibi çalıştı.
e18r

@ e18r Bayt üretiyor, evet, ama varsayılan karakter setindeki bu göstergeden beri hangisini bilmiyorsunuz. En azından .getBytes (desiredEncoding) kullanın.
miktar

@petmez aptal soru: JAVA'da "" .getBytes (UTF_8)) gibi bir şey; (boş bir dizgide getBytes) yapmak güvenli bir şey mi? 'yasal' mı? Yoksa şunu yapabilir miyim: = new byte [0]; ?
Robert Achmann

1
@RobertAchmann "" .getbytes ("UTF-8") boş bir dizi döndürmeli ve tamamen yasaldır.
Jazzepi

33

Java 6'da, tam olarak ne istediğinizi yapan bir yöntem vardır:

private static final byte[] CDRIVES = javax.xml.bind.DatatypeConverter.parseHexBinary("e04fd020ea3a6910a2d808002b30309d")

Alternatif olarak Google Guava'yı kullanabilirsiniz :

import com.google.common.io.BaseEncoding;
private static final byte[] CDRIVES = BaseEncoding.base16().lowerCase().decode("E04FD020ea3a6910a2d808002b30309d".toLowerCase());

Küçük diziler kullandığınızda Guava yöntemi aşırıya kaçıyor. Ancak Guava'nın giriş akışlarını ayrıştırabilen sürümleri de vardır. Büyük onaltılık girdilerle uğraşırken bu hoş bir özelliktir.


Guava örneği yazıldığı gibi çalışmıyor - base16().lowerCase().decode(...)küçük harfli onaltılık basamaklarınız olması gerekir. docs.guava-libraries.googlecode.com/git/javadoc/com/google/…
Peter

@PeterDeGlopper İyi bulma, cevabı güncelledim, böylece kod artık hem küçük hem de büyük harfli dizeleri işliyor.
stefan.schwetschke

1
javax.xml.bindJava 9'da ne yazık ki kaldırıldı
randomdude999

7

Bayt dizileri yerine bu değerleri depolamak için Java UUID sınıfını kullanabilirsiniz:

UUID

public UUID(long mostSigBits,
            long leastSigBits)

Belirtilen verileri kullanarak yeni bir UUID oluşturur. mostSigBits, UUID'nin en önemli 64 biti için kullanılır ve leastSigBits, UUID'nin en az önemli 64 biti haline gelir.


2

Temiz bir süreç söz konusu olduğunda ByteArrayOutputStream nesnesini kullanabilirsiniz ...

ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();

// kullanarak tüm değerleri tek tek bObj'e yaz

bObj.write(byte value)

// bittiğinde byte [] tuşunu kullanarak

CDRIVES = bObj.toByteArray();

// CMYDOCS ve IEFRAME için de benzer işlemleri tekrarlayabildiğinizden,

NOT Gerçekten küçük bir diziniz varsa bu etkili bir çözüm değildir.


2

Kütüphanesi olmayan bir çözüm, dinamik uzunluk döndürüldü, işaretsiz tam sayı yorumu (ikisinin tamamlayıcısı değil)

    public static byte[] numToBytes(int num){
    if(num == 0){
        return new byte[]{};
    }else if(num < 256){
        return new byte[]{ (byte)(num) };
    }else if(num < 65536){
        return new byte[]{ (byte)(num >>> 8),(byte)num };
    }else if(num < 16777216){
        return new byte[]{ (byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }else{ // up to 2,147,483,647
        return new byte[]{ (byte)(num >>> 24),(byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }
}

1

Bu durumda tercih ettiğim seçenek y hex ve binary org.apache.commons.codec.binary.Hexarasında dönüştürme için kullanışlı API'lere sahip kullanmaktır String. Örneğin:

  1. Hex.decodeHex(char[] data)DecoderExceptiondizide onaltılı olmayan karakterler varsa veya tek sayıda karakter varsa a atar .

  2. Hex.encodeHex(byte[] data)yukarıdaki kod çözme yönteminin karşılığıdır ve char[].

  3. Hex.encodeHexString(byte[] data)bir bytediziden a String.

Kullanımı: Hex.decodeHex("dd645a2564cbe648c8336d2be5eafaa6".toCharArray())


1

Bu yardımcı program işlevini kullanabilirsiniz:

public static byte[] fromHexString(String src) {
    byte[] biBytes = new BigInteger("10" + src.replaceAll("\\s", ""), 16).toByteArray();
    return Arrays.copyOfRange(biBytes, 1, biBytes.length);
}

Denys Séguret ve stefan.schwetschke varyantlarının aksine, giriş dizesine ayırıcı semboller (boşluklar, sekmeler vb.) Eklenmesine izin vererek daha okunabilir hale getirir.

Kullanım örneği:

private static final byte[] CDRIVES
    = fromHexString("e0 4f d0 20 ea 3a 69 10 a2 d8 08 00 2b 30 30 9d");
private static final byte[] CMYDOCS
    = fromHexString("BA8A0D4525ADD01198A80800361B1103");
private static final byte[] IEFRAME
    = fromHexString("80531c87 a0426910 a2ea0800 2b30309d");

1

Derleme zamanında heks numaraları ile tayin edilebilir küçük iç türü, karakter olarak,

private static final char[] CDRIVES_char = new char[] {0xe0, 0xf4, ...};

Eşdeğer bir bayt dizisine sahip olmak için dönüşümler şu şekilde dağıtılabilir:

public static byte[] charToByteArray(char[] x)
{
    final byte[] res = new byte[x.length];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = (byte) x[i];
    }
    return res;
}

public static byte[][] charToByteArray(char[][] x)
{
    final byte[][] res = new byte[x.length][];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = charToByteArray(x[i]);
    }
    return res;
}

-2
private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};

ve erişim sonrasında bayta dönüştürür.

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.