Bir bayt dizisini sayısal değerine (Java) nasıl dönüştürebilirim?


91

8 baytlık bir dizim var ve onu karşılık gelen sayısal değerine dönüştürmek istiyorum.

Örneğin

byte[] by = new byte[8];  // the byte array is stored in 'by'

// CONVERSION OPERATION
// return the numeric value

Yukarıdaki dönüştürme işlemini gerçekleştirecek bir yöntem istiyorum.


4
"Sayısal değer" ile neyi kastediyorsunuz? Baytlar ikili olarak bir tamsayıyı mı (uzun) yoksa kayan nokta sayısını (çift) mı temsil ediyor? Bir sayının dize temsili mi? Veya başka bir temsil?
starblue


NB: TacB0sS'nin bağlantısı aslında aradığım şeydi - hem ileriye hem de geriye dönüşüm.
Jay Taylor

new BigInteger(by).longValue()
user207421

Yanıtlar:


108

İlk baytın en az önemli bayt olduğunu varsayarsak:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value += ((long) by[i] & 0xffL) << (8 * i);
}

İlk bayt en önemli olanıdır, o zaman biraz farklıdır:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value = (value << 8) + (by[i] & 0xff);
}

8 bayttan fazlasına sahipseniz uzun BigInteger ile değiştirin .

Hatalarımın düzeltilmesi için Aaron Digulla'ya teşekkürler.


8
-1 bayt işaretli değerlerdir! Ve pow () 'yu shift (<<) ile değiştirin! "değer = (değer << 8) + ([i] ve 0xff tarafından)"
Aaron Digulla

Kaydırma operatörü (<<) sağdan sola önceliğe sahip mi? Yukarıdaki kod nasıl çalışır? Benim için gayet iyi çalışıyor. Sadece çalıştığını bilmek istiyorum. Thanx peşin
suraj

@Mnementh: Kaydırma operatörü (<<) sağdan sola önceliğe sahip mi? Yukarıdaki kod nasıl çalışır? Benim için gayet iyi çalışıyor. Sadece çalıştığını bilmek istiyorum. Thanx peşin
suraj

5
Benim yaptığımla aynı sorunu yaşayan başka biri varsa, ilk örnekte [i] ile uzun bir sayıya çevrilmelidir, aksi takdirde yalnızca 2 ^ 32'den küçük değerler için çalışır. Yani,value += ((long)by[i] & 0xffL) << (8 * i);
Luke

115

Birinin bir Bufferparçası olarak sağlanan 'ler kullanılabilirjava.nioDönüştürmeyi gerçekleştirmek için paketin bir .

Burada kaynak byte[]dizinin uzunluğu 8'dir, bu boyut bir longdeğere karşılık gelen boyuttur .

İlk olarak, byte[]dizi bir a dizisine sarılır ByteBufferve ardından değeri ByteBuffer.getLongelde etmek için yöntem çağrılır long:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 4});
long l = bb.getLong();

System.out.println(l);

Sonuç

4

ByteBuffer.getLongYorumlarda yönteme işaret ettiği için dfa'ya teşekkür etmek istiyorum .


Bu durumda uygulanabilir olmasa da, Bufferlerin güzelliği birden çok değere sahip bir diziye bakmakla birlikte gelir.

Örneğin, eğer bir 8 bayt dizisi vardı ve biz iki gibi kullanmak istedi int, biz sarabilirdiniz değerler byte[]bir in diziyi ByteBufferbir olarak görülüyor, IntBufferve değerleri elde IntBuffer.get:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 1, 0, 0, 0, 4});
IntBuffer ib = bb.asIntBuffer();
int i0 = ib.get(0);
int i1 = ib.get(1);

System.out.println(i0);
System.out.println(i1);

Sonuç:

1
4

Peki ya ByteBuffer.wrap (yeni bayt [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong ()? bu yöntem sonraki 8 baytı okumalı ve bunları uzun bir
dfa'ya

@dfa: Bunu belirttiğiniz için teşekkürler, kesinlikle işe yarıyor gibi görünüyor - yanıtı düzenleyeceğim. :)
coobird

16

Bu 8 baytlık bir sayısal değerse, deneyebilirsiniz:

BigInteger n = new BigInteger(byteArray);

Bu bir UTF-8 karakter arabelleğiyse, deneyebilirsiniz:

BigInteger n = new BigInteger(new String(byteArray, "UTF-8"));

İlk kod parçacığından hemen sonra biterse veya dizeyi bir "sayısal değere" dönüştürmek için bazı kodlar içeriyorsa, bu yanıta oy verirdim. Olduğu gibi, cevabınızın ikinci yarısı sonuçsuz görünüyor.
Laurence Gonsalves

Ben ilk etapta demek değil ne cevabımı değişti
Vincent Robert


9

BigInteger'ı değişken uzunluklu baytlar için de kullanabilirsiniz. İhtiyaçlarınıza uygun olanı Uzun, Tamsayı veya Kısa olarak dönüştürebilirsiniz.

new BigInteger(bytes).intValue();

veya polariteyi belirtmek için:

new BigInteger(1, bytes).intValue();


1

Dizideki her hücre, işaretsiz tamsayı olarak değerlendirilir:

private int unsignedIntFromByteArray(byte[] bytes) {
int res = 0;
if (bytes == null)
    return res;


for (int i=0;i<bytes.length;i++){
    res = res | ((bytes[i] & 0xff) << i*8);
}
return res;
}

Sadece 0xFFL kullanmam gerektiğine dikkat edin, aksi takdirde int 0xFF'den long'a çevirme Long.toHexString (l) yazdırdığımda çok sayıda yanlış 1 bit setine sahipti.
Luke

0xFFL kullanmanız gerekir, aksi takdirde imza uzantısı alırsınız.
Gray

0
public static long byteArrayToLong(byte[] bytes) {
    return ((long) (bytes[0]) << 56)
            + (((long) bytes[1] & 0xFF) << 48)
            + ((long) (bytes[2] & 0xFF) << 40)
            + ((long) (bytes[3] & 0xFF) << 32)
            + ((long) (bytes[4] & 0xFF) << 24)
            + ((bytes[5] & 0xFF) << 16)
            + ((bytes[6] & 0xFF) << 8)
            + (bytes[7] & 0xFF);
}

bayt dizisini (uzun 8 bayt) uzunluğa dönüştü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.