Jak przekonwertować tablicę bajtów na jej wartość liczbową (Java)?


89

Mam tablicę 8-bajtową i chcę przekonwertować ją na odpowiednią wartość liczbową.

na przykład

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

// CONVERSION OPERATION
// return the numeric value

Chcę metody, która wykona powyższą operację konwersji.


4
Co rozumiesz przez „wartość liczbową”? Czy bajty reprezentują liczbę całkowitą (długą) czy zmiennoprzecinkową (podwójną) w systemie binarnym? Czy są one ciągiem reprezentującym liczbę? A może jeszcze inna reprezentacja?
starblue


Uwaga: link TacB0sS był tym, czego szukałem - zarówno konwersją do przodu, jak i do tyłu.
Jay Taylor

new BigInteger(by).longValue()
Markiz Lorne

Odpowiedzi:


106

Zakładając, że pierwszy bajt jest najmniej znaczącym bajtem:

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

Czy pierwszy bajt jest najbardziej znaczący, to jest trochę inny:

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

Zamień long na BigInteger , jeśli masz więcej niż 8 bajtów.

Podziękowania dla Aarona Digulla za poprawienie moich błędów.


8
-1 bajtów to wartości ze znakiem! I zamień pow () na shift (<<)! "wartość = (wartość << 8) + (przez [i] & 0xff)"
Aaron Digulla

Czy operator przesunięcia (<<) ma pierwszeństwo od prawej do lewej strony? Jak działa powyższy kod? Dla mnie działa dobrze. Chcę tylko wiedzieć, jak działa. Dzięki z góry
suraj

@Mnementh: Czy operator zmiany (<<) ma pierwszeństwo od prawej do lewej? Jak działa powyższy kod? Dla mnie działa dobrze. Chcę tylko wiedzieć, jak działa. Dzięki z góry
suraj

5
W przypadku, gdy ktoś inny ma ten sam problem, co ja, w pierwszym przykładzie, przez [i] należy rzutować na długość, w przeciwnym razie działa to tylko dla wartości mniejszych niż 2 ^ 32. To znaczyvalue += ((long)by[i] & 0xffL) << (8 * i);
Łukasz

115

Aby wykonać konwersję, można użyć Buffers, które są dostarczane jako część java.niopakietu.

W tym przypadku byte[]tablica źródłowa ma długość 8, czyli rozmiar odpowiadający longwartości.

Najpierw byte[]tablica jest zawijana a ByteBuffer, a następnie ByteBuffer.getLongwywoływana jest metoda w celu uzyskania longwartości:

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

System.out.println(l);

Wynik

4

Chciałbym podziękować dfa za wskazanie ByteBuffer.getLongmetody w komentarzach.


Chociaż może to nie mieć zastosowania w tej sytuacji, piękno tych funkcji Bufferpolega na spojrzeniu na tablicę z wieloma wartościami.

Na przykład, gdybyśmy mieli 8-bajtową tablicę i chcielibyśmy zobaczyć ją jako dwie intwartości, moglibyśmy zawinąć byte[]tablicę w an ByteBuffer, która jest wyświetlana jako a IntBufferi uzyskać wartości przez 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);

Wynik:

1
4

a co z ByteBuffer.wrap (new byte [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong ()? ta metoda powinna odczytać następne 8 bajtów i przekonwertować je na długie
dfa

@dfa: Dziękuję za zwrócenie uwagi, na pewno działa - poprawię odpowiedź. :)
coobird

16

Jeśli jest to 8-bajtowa wartość liczbowa, możesz spróbować:

BigInteger n = new BigInteger(byteArray);

Jeśli jest to bufor znaków UTF-8, możesz spróbować:

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

Głosowałbym za tą odpowiedzią, gdyby kończyła się zaraz po pierwszym fragmencie kodu lub gdyby zawierała jakiś kod konwertujący ciąg na „wartość numeryczną”. W obecnej sytuacji druga połowa Twojej odpowiedzi wydaje się nie być sekwencją.
Laurence Gonsalves

Nie to, co miałem na myśli w pierwszej kolejności, zmieniłem odpowiedź
Vincent Robert


9

Możesz również użyć BigInteger dla bajtów o zmiennej długości. Możesz przekonwertować go na długi, całkowity lub krótki, w zależności od potrzeb.

new BigInteger(bytes).intValue();

lub do oznaczenia biegunowości:

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


1

Każda komórka w tablicy jest traktowana jako int bez znaku:

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

Tylko uwaga, że ​​potrzebowałem użyć 0xFFL, w przeciwnym razie rzutowanie z int 0xFF na long miało całą masę nieprawidłowych 1 bitów ustawionych podczas drukowania Long.toHexString (l).
Łukasz

Musisz użyć 0xFFL, w przeciwnym razie otrzymasz rozszerzenie znaku.
Szary
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.