Liczba całkowita Java na tablicę bajtów

190

Mam liczbę całkowitą: 1695609641

kiedy używam metody:

String hex = Integer.toHexString(1695609641);
system.out.println(hex); 

daje:

6510f329

ale chcę tablicę bajtów:

byte[] bytearray = new byte[] { (byte) 0x65, (byte)0x10, (byte)0xf3, (byte)0x29};

Jak mogę to zrobić?

Stefan
źródło

Odpowiedzi:

293

korzystanie z ByteBuffer Java NIO jest bardzo proste:

byte[] bytes = ByteBuffer.allocate(4).putInt(1695609641).array();

for (byte b : bytes) {
   System.out.format("0x%x ", b);
}

wynik:

0x65 0x10 0xf3 0x29 
dfa
źródło
4
Lub użyj formatu, "0x%02X"jeśli zawsze chcesz mieć dwa znaki szesnastkowe, a także wielkie litery szesnastkowe, np . System.out.format("0x%02X", (byte) 10)Ekrany 0x0A.
Maarten Bodewes
12
Możesz użyć Integer.SIZE / 8, aby uniknąć twardego zakodowania 4, który jest wzorem, który działa dobrze dla innych typów, takich jak Long.
davenpcj
3
@davenpcj Możesz nawet użyć Integer.SIZE / Byte.SIZE
rkosegi
11
@rkosegi Lub nawet Integer.BYTES od Java 8 :)
drvdijk
1
Wątek @MaartenBodewes nie ma nic do widocznego formatowania, ale operacja typu natywnego
Jacek Cz
146

Co powiesz na:

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

Pomysł nie jest mój . Wziąłem to z jakiegoś posta na dzone.com .

Grzegorz Oledzki
źródło
44
Rozumiem twój punkt widzenia, ale dla tego konkretnego zadania „mój” kod jest bardziej deklaratywny i przejrzysty niż jakiś „magiczny” ByteBuffer, który należy sprawdzić, aby zobaczyć, co robi.
Grzegorz Oledzki
24
@Kevin - to bardzo trudne - istnieje wiele przypadków, w których ten rodzaj kodu jest odpowiedni, np. W przetwarzaniu obrazu. Biblioteki JDK są ogólnie świetne, ale nie obejmują i / lub nie są zoptymalizowane dla wszystkich przypadków użycia.
mikera
14
Zgoda; narzut i złożoność ByteBuffer mogą nie być odpowiednie w porównaniu z niektórymi prostymi i dobrze znanymi operacjami bajtowymi.
swdunlop
6
Inną kwestią, którą dodam, jest to, że użyłeś niepodpisanego prawego operatora zmiany >>>zamiast prawego operatora zmiany >>( docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html ), więc zachowanie może być inne niż pożądane / zgodnie z oczekiwaniami z numerami podpisanymi vs niepodpisanymi
RobV
4
To podejście wydaje się być odrobinę szybsze niż wspomniane metody ByteBuffer lub BigInteger. Coś innego, co należy wziąć pod uwagę, jeśli będziesz wykonywać wiele konwersji.
poszukujący
45

BigInteger.valueOf(1695609641).toByteArray()

vmpn
źródło
2
jaką masz gwarancję, że da to tablicę 4-bajtową?
MeBigFatGuy,
2
Dokładnie to, co napisał MeBigFatGuy. Javadoc BigInteger.toByteArray()stanów: „Tablica będzie zawierać minimalną liczbę bajtów wymaganą do reprezentacji tego BigInteger ...”
icza
2
Gdzie w pytaniu wymaga tablicy bajtów o stałej długości 4? W zależności od algorytmu, który ma być częścią ciebie, możesz wykorzystać długość tablicy
vmpn 20.04.2014
jest to o wiele bardziej dynamiczne i powinno być właściwą odpowiedzią. Możesz po prostu zrobić dodatek do tablicy, aby utworzyć żądany rozmiar, jeśli chcesz. Zwłaszcza gdy trzeba wziąć pod uwagę wartości int podpisane w Javie.
Droid Chris
2
Wydaje się, że tworzy to jeden bajt dla 0x7f i dwa bajty dla 0x80 (dwa bajty to: 0x0 0x80).
Scot,
26
byte[] IntToByteArray( int data ) {    
    byte[] result = new byte[4];
    result[0] = (byte) ((data & 0xFF000000) >> 24);
    result[1] = (byte) ((data & 0x00FF0000) >> 16);
    result[2] = (byte) ((data & 0x0000FF00) >> 8);
    result[3] = (byte) ((data & 0x000000FF) >> 0);
    return result;        
}
Jurij Finczenko
źródło
22

Używanie Guawy :

byte[] bytearray = Ints.toByteArray(1695609641);
Aleksandr Dubinsky
źródło
7
byte[] conv = new byte[4];
conv[3] = (byte) input & 0xff;
input >>= 8;
conv[2] = (byte) input & 0xff;
input >>= 8;
conv[1] = (byte) input & 0xff;
input >>= 8;
conv[0] = (byte) input;
Carl Smotricz
źródło
2
Wyodrębnia to najmniej znaczące 8 bajtów. Unika także przeciągania znaku numeru wejściowego do przekształconego oktetu.
Carl Smotricz
stackoverflow.com/questions/35305634/... - czy możesz rozwiązać ten C # w Javie?
5
public static byte[] intToBytes(int x) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(bos);
    out.writeInt(x);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}
lyon819
źródło
4

Fragmenty poniżej działają przynajmniej w przypadku wysyłania int przez UDP.

int na tablicę bajtów:

public byte[] intToBytes(int my_int) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = new ObjectOutputStream(bos);
    out.writeInt(my_int);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}

tablica bajtów na int:

public int bytesToInt(byte[] int_bytes) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream(int_bytes);
    ObjectInputStream ois = new ObjectInputStream(bis);
    int my_int = ois.readInt();
    ois.close();
    return my_int;
}
HaoQi Li
źródło
4
użycie ObjectOutputStream jest nieprawidłowe. Użyj DataOutputStream, użycie OOS sprawia, że ​​tablica bajtów nie ma 4 bajtów.
MeBigFatGuy,
2

Ponieważ na ogół chciałbyś przekonwertować tę tablicę z powrotem na liczbę int w późniejszym czasie, oto metody konwersji tablicy ints na tablicę bajtów i odwrotnie:

public static byte[] convertToByteArray(final int[] pIntArray)
{
    final byte[] array = new byte[pIntArray.length * 4];
    for (int j = 0; j < pIntArray.length; j++)
    {
        final int c = pIntArray[j];
        array[j * 4] = (byte)((c & 0xFF000000) >> 24);
        array[j * 4 + 1] = (byte)((c & 0xFF0000) >> 16);
        array[j * 4 + 2] = (byte)((c & 0xFF00) >> 8);
        array[j * 4 + 3] = (byte)(c & 0xFF);
    }
    return array;
}

public static int[] convertToIntArray(final byte[] pByteArray)
{
    final int[] array = new int[pByteArray.length / 4];
    for (int i = 0; i < array.length; i++)
        array[i] = (((int)(pByteArray[i * 4]) << 24) & 0xFF000000) |
                (((int)(pByteArray[i * 4 + 1]) << 16) & 0xFF0000) |
                (((int)(pByteArray[i * 4 + 2]) << 8) & 0xFF00) |
                ((int)(pByteArray[i * 4 + 3]) & 0xFF);
    return array;
}

Zauważ, że ze względu na propagację znaków i tym podobne, „& 0xFF ...” są potrzebne przy konwersji z powrotem na int.

jytou
źródło
1
integer & 0xFF

dla pierwszego bajtu

(integer >> 8) & 0xFF

dla drugiej i pętli itp., zapisywanie do wstępnie przydzielonej tablicy bajtów. Niestety, trochę niechlujny.

Brian Agnew
źródło
1

Klasa org.apache.hadoop.hbase.util.Bytes ma kilka przydatnych metod konwersji byte [], ale możesz nie chcieć dodawać całego słoika HBase do swojego projektu tylko w tym celu. Zaskakujące jest to, że w JDK brakuje takiej metody AFAIK, ale także oczywistych bibliotek, takich jak commons io.

mlohbihler
źródło
1

Moja próba:

public static byte[] toBytes(final int intVal, final int... intArray) {
    if (intArray == null || (intArray.length == 0)) {
        return ByteBuffer.allocate(4).putInt(intVal).array();
    } else {
        final ByteBuffer bb = ByteBuffer.allocate(4 + (intArray.length * 4)).putInt(intVal);
        for (final int val : intArray) {
            bb.putInt(val);
        }
        return bb.array();
    }
}

Dzięki niemu możesz to zrobić:

byte[] fourBytes = toBytes(0x01020304);
byte[] eightBytes = toBytes(0x01020304, 0x05060708);

Pełna klasa jest tutaj: https://gist.github.com/superbob/6548493 , obsługuje inicjalizację od krótkich lub długich

byte[] eightBytesAgain = toBytes(0x0102030405060708L);
superbob
źródło
1

Jeśli używasz apache-commons

public static byte[] toByteArray(int value) {
    byte result[] = new byte[4];
    return Conversion.intToByteArray(value, 0, result, 0, 4);
}
Neeraj
źródło