Konwertuj liczbę całkowitą na tablicę bajtów (Java)

137

jaki jest szybki sposób na przekształcenie a Integerw Byte Array?

na przykład 0xAABBCCDD => {AA, BB, CC, DD}

Jaskier
źródło
1
Czy ma znaczenie, jaki format ma wynikowa tablica bajtów? Co z tym zrobisz?
skaffman

Odpowiedzi:

237

Przyjrzyj się klasie ByteBuffer .

ByteBuffer b = ByteBuffer.allocate(4);
//b.order(ByteOrder.BIG_ENDIAN); // optional, the initial order of a byte buffer is always BIG_ENDIAN.
b.putInt(0xAABBCCDD);

byte[] result = b.array();

Ustawianie kolejności bajtów, zapewnia, że result[0] == 0xAA, result[1] == 0xBB, result[2] == 0xCCi result[3] == 0xDD.

Lub możesz zrobić to ręcznie:

byte[] toBytes(int i)
{
  byte[] result = new byte[4];

  result[0] = (byte) (i >> 24);
  result[1] = (byte) (i >> 16);
  result[2] = (byte) (i >> 8);
  result[3] = (byte) (i /*>> 0*/);

  return result;
}

ByteBufferKlasa została zaprojektowana dla tych brudnych rąk zadań chociaż. W rzeczywistości prywatny java.nio.Bitsdefiniuje te metody pomocnicze, które są używane przez ByteBuffer.putInt():

private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >>  8); }
private static byte int0(int x) { return (byte)(x >>  0); }
Gregory Pakosz
źródło
3
to działałoby dobrze, gdyby bufor bajtów już tam jest ... w przeciwnym razie wydaje się, że alokacja zajęłaby więcej czasu niż po prostu przydzielenie tablicy bajtów o długości 4 i przesunięcie ręcznie ... ale prawdopodobnie rozmawiamy o małych różnicach.
Jason S
Instancja ByteBuffer może być buforowana; i tak wewnętrznie jest na pewno zaimplementowany z przesuwaniem i maskowaniem.
Gregory Pakosz
4
To doskonała odpowiedź. Zauważ, że big-endian jest określoną wartością domyślną, a metody są „łańcuchowe”, a argument pozycji jest opcjonalny, więc wszystko redukuje się do: byte [] result = ByteBuffer.allocate (4) .putInt (0xAABBCCDD) .array ( ); Oczywiście, jeśli robisz to wielokrotnie i łączysz wszystkie wyniki razem (co jest powszechne, gdy robisz tego rodzaju rzeczy), przydziel pojedynczy bufor i wielokrotnie wstawFoo () do niego wszystkie potrzebne rzeczy - będzie śledzić przesunięcie w trakcie. To naprawdę niezwykle przydatne zajęcia.
Kevin Bourrillion
co to przynosi podpisanym typom?
Gregory Pakosz
3
Kto nie wie. PutInt zawsze zapisze 4 bajty, bez względu na rozmiar wejściowej liczby całkowitej. Jeśli chcesz tylko 2 bajty, użyj putShort, itd ...
bvdb
36

Używając BigInteger:

private byte[] bigIntToByteArray( final int i ) {
    BigInteger bigInt = BigInteger.valueOf(i);      
    return bigInt.toByteArray();
}

Używając DataOutputStream:

private byte[] intToByteArray ( final int i ) throws IOException {      
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}

Używając ByteBuffer:

public byte[] intToBytes( final int i ) {
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.putInt(i); 
    return bb.array();
}
Pascal Thivent
źródło
5
zwróć jednak uwagę na kolejność bajtów
Gregory Pakosz
1
Czy ByteBuffer wydaje int bez znaku?
Arun George
@Pascal przy użyciu ByteBuffer Próbowałem z ByteBuffer bb = ByteBuffer.allocate (3); W tym celu daje java.nio.BufferOverflowException, nie rozumiem, dlaczego nie działa dla wartości mniejszej niż 4? Czy możesz wyjaśnić?
Sanjay Jain
@SanjayJain Otrzymujesz wyjątek od przepełnienia buforu, ponieważ wartości int w Javie mają rozmiar 32-bitowy lub 4 bajty, a zatem wymagają przydzielenia co najmniej 4 bajtów pamięci w ByteBuffer.
szokujące
@GregoryPakosz ma rację co do kolejności bajtów. Jego odpowiedź ByteBufferjest bardziej intuicyjna, jeśli masz do czynienia z int większym niż 2 ^ 31 - 1.
ordonezalex
31

użyj tej funkcji, która działa dla mnie

public byte[] toByteArray(int value) {
    return new byte[] {
            (byte)(value >> 24),
            (byte)(value >> 16),
            (byte)(value >> 8),
            (byte)value};
}

tłumaczy int na wartość bajtową

daz
źródło
Nic też nie jest warte, że zadziała to niezależnie od najbardziej znaczącego bitu i będzie bardziej wydajne w porównaniu z innymi odpowiedziami. Można również użyć „>>”.
algolicious
1
Takie bezpośrednie rozwiązanie jest z pewnością szybsze niż wywołanie dowolnej metody bibliotecznej. Czasami musisz po prostu bawić się bitami bezpośrednio za pomocą kilku linii kodu, zamiast ponosić cały dodatkowy narzut wywołań metod bibliotecznych.
David R Tribble
I to dobrze konwertuje między językami, więc jest dobre do tworzenia oprogramowania w wielu językach.
Koordynator
15

Jeśli lubisz guawę , możesz użyć jej Intsklasy:


Do intbyte[]użyj toByteArray():

byte[] byteArray = Ints.toByteArray(0xAABBCCDD);

Wynik jest {0xAA, 0xBB, 0xCC, 0xDD}.


Jego odwrotność to fromByteArray()lub fromBytes():

int intValue = Ints.fromByteArray(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD});
int intValue = Ints.fromBytes((byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD);

Wynik jest 0xAABBCCDD.

Ostry ból
źródło
8

Możesz użyć BigInteger:

Z liczb całkowitych:

byte[] array = BigInteger.valueOf(0xAABBCCDD).toByteArray();
System.out.println(Arrays.toString(array))
// --> {-86, -69, -52, -35 }

Zwracana tablica ma rozmiar wymagany do przedstawienia liczby, więc może mieć rozmiar 1, na przykład do reprezentowania 1. Jednak rozmiar nie może być większy niż cztery bajty, jeśli przekazywana jest wartość int.

From Strings:

BigInteger v = new BigInteger("AABBCCDD", 16);
byte[] array = v.toByteArray();

Musisz jednak uważać, jeśli pierwszy bajt jest wyższy 0x7F(tak jak w tym przypadku), gdzie BigInteger wstawiłby bajt 0x00 na początku tablicy. Jest to potrzebne do rozróżnienia wartości dodatnich i ujemnych.

notnoop
źródło
dzięki! Ale skoro to jest BigInteger, czy ints będą się prawidłowo zawijać? Czy to liczby całkowite, które są poza Integer.MAX_VALUE, ale nadal można je przedstawić za pomocą tylko 4 bajtów?
Jaskier
1
Z pewnością nie jest to szybkie do wykonania. ;)
Peter Lawrey
To nie jest dobra opcja. Nie tylko może dodać bajt 0x00, ale może również usunąć zera wiodące.
ZZ Coder,
1

Proste rozwiązanie, które poprawnie obsługuje ByteOrder:

ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(yourInt).array();

helmy
źródło
1

bardzo łatwe z systemem Android

int i=10000;
byte b1=(byte)Color.alpha(i);
byte b2=(byte)Color.red(i);
byte b3=(byte)Color.green(i);
byte b4=(byte)Color.blue(i);
Mukesh Bambhaniya
źródło
1

To ci pomoże.

import java.nio.ByteBuffer;
import java.util.Arrays;

public class MyClass
{
    public static void main(String args[]) {
        byte [] hbhbytes = ByteBuffer.allocate(4).putInt(16666666).array();

        System.out.println(Arrays.toString(hbhbytes));
    }
}
wai
źródło
0

Może również przesuwać -

byte[] ba = new byte[4];
int val = Integer.MAX_VALUE;

for(byte i=0;i<4;i++)
    ba[i] = (byte)(val >> i*8);
    //ba[3-i] = (byte)(val >> i*8); //Big-endian
Matt
źródło
0

Oto metoda, która powinna dobrze wykonać zadanie.

public byte[] toByteArray(int value)
{
    final byte[] destination = new byte[Integer.BYTES];
    for(int index = Integer.BYTES - 1; index >= 0; index--)
    {
        destination[i] = (byte) value;
        value = value >> 8;
    };
    return destination;
};
user3424779
źródło
0

To moje rozwiązanie:

public void getBytes(int val) {
    byte[] bytes = new byte[Integer.BYTES];
    for (int i = 0;i < bytes.length; i ++) {
        int j = val % Byte.MAX_VALUE;
        bytes[i] = (j == 0 ? Byte.MAX_VALUE : j);
    }
}

Również Stringmetoda y:

public void getBytes(int val) {
    String hex = Integer.toHexString(val);
    byte[] val = new byte[hex.length()/2]; // because byte is 2 hex chars
    for (int i = 0; i < hex.length(); i+=2)
        val[i] = Byte.parseByte("0x" + hex.substring(i, i+2), 16);
    return val;
}
Muskovets
źródło