Konwersja tablicy bajtów na liczbę całkowitą w Javie i odwrotnie

Chcę zapisać pewne dane do tablic bajtowych w Javie. Zasadniczo tylko liczby, które mogą zająć do 2 bajtów na liczbę.

Chciałbym wiedzieć, jak mogę przekonwertować liczbę całkowitą na tablicę o długości 2 bajtów i odwrotnie. Znalazłem wiele rozwiązań w googlach, ale większość z nich nie wyjaśnia, co się dzieje w kodzie. Jest wiele rzeczy, których naprawdę nie rozumiem, więc byłbym wdzięczny za podstawowe Wyjaśnienie.

Author: Wrigglenite, 2011-10-01

8 answers

Użyj klas znalezionych w java.nio przestrzeni nazw, w szczególnościByteBuffer. Może wykonać całą pracę za Ciebie.

byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1

ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }
 240
Author: Jeff Mercado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-01 08:36:31
byte[] toByteArray(int value) {
     return  ByteBuffer.allocate(4).putInt(value).array();
}

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

int fromByteArray(byte[] bytes) {
     return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, | 
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
     return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
     return ((bytes[0] & 0xFF) << 24) | 
            ((bytes[1] & 0xFF) << 16) | 
            ((bytes[2] & 0xFF) << 8 ) | 
            ((bytes[3] & 0xFF) << 0 );
}

Podczas pakowania podpisanych bajtów do int, każdy bajt musi być maskowany, ponieważ jest rozszerzony na 32 bity (a nie na zero) ze względu na arytmetyczną regułę promocji (opisaną w JLS, konwersje i promocje).

W Java Puzzlers ("A Big Delight in Every Byte") Joshua Bloch i Neal Gafter znajduje się ciekawa zagadka . Podczas porównywania wartości bajtu z wartością int, bajt jest rozszerzony na int i wtedy wartość ta jest w porównaniu do innych int

byte[] bytes = (…)
if (bytes[0] == 0xFF) {
   // dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}

Zauważ, że wszystkie typy liczbowe są podpisywane w języku Java, z wyjątkiem tego, że char jest 16-bitowym, niepodpisanym typem liczb całkowitych.

 133
Author: Jarek Przygódzki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-21 22:41:04

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

new BigInteger(bytes).intValue();

Lub oznaczanie polaryzacji:

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

Aby odzyskać bajty wystarczy:

new BigInteger(bytes).toByteArray()
 60
Author: Jamel Toms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-25 19:57:21

Podstawowa implementacja byłaby mniej więcej taka:

public class Test {
    public static void main(String[] args) {
        int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
        byte[] output = new byte[input.length * 2];

        for (int i = 0, j = 0; i < input.length; i++, j+=2) {
            output[j] = (byte)(input[i] & 0xff);
            output[j+1] = (byte)((input[i] >> 8) & 0xff);
        }

        for (int i = 0; i < output.length; i++)
            System.out.format("%02x\n",output[i]);
    }
}

Aby zrozumieć rzeczy możesz przeczytać ten artykuł WP: http://en.wikipedia.org/wiki/Endianness

Powyższy kod źródłowy wyświetli 34 12 78 56 bc 9a. Pierwsze 2 bajty (34 12) reprezentują pierwszą liczbę całkowitą, itd. Powyższy kod źródłowy koduje liczby całkowite w formacie little endian.

 5
Author: prekageo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-01 08:25:00
/** length should be less than 4 (for int) **/
public long byteToInt(byte[] bytes, int length) {
        int val = 0;
        if(length>4) throw new RuntimeException("Too big to fit in int");
        for (int i = 0; i < length; i++) {
            val=val<<8;
            val=val|(bytes[i] & 0xFF);
        }
        return val;
    }
 2
Author: Dhaval Rami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 20:41:50

Ktoś z wymogiem, gdzie muszą czytać z bitów, powiedzmy, że musisz czytać tylko z 3 bitów, ale potrzebujesz signed integer, a następnie użyj następującego:

data is of type: java.util.BitSet

new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3

Magiczną liczbę 3 można zastąpić liczbą bitów (nie bajtów) , których używasz.

 0
Author: Vishrant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 17:21:31

Jak często, guava ma to, czego potrzebujesz.

Aby przejść z tablicy bajtów do int: Ints.fromBytesArray, doc tutaj

Aby przejść z int do tablicy bajtów: Ints.toByteArray, doc tutaj

 0
Author: jeremie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-21 20:46:10

Myślę, że jest to najlepszy tryb do rzucania do int

   public int ByteToint(Byte B){
        String comb;
        int out=0;
        comb=B+"";
        salida= Integer.parseInt(comb);
        out=out+128;
        return out;
    }

Pierwszy bajt comvert do String

comb=B+"";

Następny krok to comvert do int

out= Integer.parseInt(comb);

Ale byte jest w rage od -128 do 127 z tego powodu, myślę, że lepiej użyć rage 0 do 255 i wystarczy to zrobić:

out=out+256;
 -7
Author: Angel Salvador Ayala Ochoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-16 11:08:17