Как преобразовать Int в беззнаковый байт и обратно

Мне нужно преобразовать число в беззнаковый байт. Число всегда меньше или равно 255, и поэтому оно будет входить в один байт.

Мне также нужно преобразовать этот байт обратно в это число. Как мне это сделать на Java? Я пробовал несколько способов, и никто не работает. Вот то, что я пытаюсь сделать сейчас:

int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);

и теперь для преобразования этого байта в число:

Byte test = new Byte(binaryByte);
int msgSize = test.intValue();

Ясно, что это не работает. По какой-то причине он всегда преобразует число в 65. Любые предложения?

Ответ 1

Байт всегда подписан в Java. Вы можете получить его значение без знака с помощью двоичного кода и с 0xFF, но:

int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234

Ответ 2

Java 8 обеспечивает Byte.toUnsignedInt преобразование byte в int беззнаковым преобразованием. В Oracle JDK это просто реализовано как return ((int) x) & 0xff;, потому что HotSpot уже понимает, как оптимизировать этот шаблон, но он может быть встроен в другие виртуальные машины. Что еще более важно, никаких предварительных знаний не требуется, чтобы понять, что делает вызов toUnsignedInt(foo).

В целом, Java 8 предоставляет методы для преобразования byte и short в unsigned int и long, а int - без знака long. Метод преобразования byte в unsigned short был намеренно опущен, поскольку JVM предоставляет арифметику только на int и long.

Чтобы преобразовать int обратно в байт, просто используйте cast: (byte)someInt. В результате сужение примитивного преобразования отбросит все, кроме последних 8 бит.

Ответ 3

Если вам просто нужно преобразовать ожидаемое 8-битное значение из подписанного int в значение без знака, вы можете использовать простое смещение битов:

int signed = -119;  // 11111111 11111111 11111111 10001001

/**
 * Use unsigned right shift operator to drop unset bits in positions 8-31
 */
int psuedoUnsigned = (signed << 24) >>> 24;  // 00000000 00000000 00000000 10001001 -> 137 base 10

/** 
 * Convert back to signed by using the sign-extension properties of the right shift operator
 */
int backToSigned = (psuedoUnsigned << 24) >> 24; // back to original bit pattern

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

Если вы используете в качестве базового типа что-то отличное от int, вам, очевидно, нужно будет скорректировать величину сдвига: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Также учтите, что вы не можете использовать тип byte, поэтому это приведет к значению, указанному другими респондентами. Наименьшим примитивным типом, который вы могли бы использовать для представления 8-битного значения без знака, будет short.

Ответ 4

Вызов Integer.toString(size) преобразуется в представление char вашего целого числа, т.е. char '5'. ASCII-представление этого символа - это значение 65.

Сначала нужно проанализировать строку до целочисленного значения, например. используя Integer.parseInt, чтобы вернуть исходное значение int.

В качестве нижней строки для подписанного/беззнакового преобразования лучше оставить String из изображения и использовать манипуляции с битами, как предлагает @JB.

Ответ 5

Решение работает отлично (спасибо!), но если вы хотите избежать кастинга и оставить работу низкого уровня в JDK, вы можете использовать DataOutputStream, чтобы написать свой int и DataInputStream, чтобы их снова прочитать. Они автоматически обрабатываются как беззнаковые байты, а затем:

Для преобразования int в двоичные байты;

ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
int val = 250;
dos.write(byteVal);
...
dos.flush();

Чтение их обратно:

// important to use a (non-Unicode!) encoding like US_ASCII or ISO-8859-1,
// i.e., one that uses one byte per character
ByteArrayInputStream bis = new ByteArrayInputStream(
   bos.toString("ISO-8859-1").getBytes("ISO-8859-1"));
DataInputStream dis = new DataInputStream(bis);
int byteVal = dis.readUnsignedByte();

Esp. полезно для обработки двоичных форматов данных (например, форматов плоских сообщений и т.д.).

Ответ 6

Обработка байтов и целых чисел без знака с помощью BigInteger:

byte[] b = ...                    // your integer in big-endian
BigInteger ui = new BigInteger(b) // let BigInteger do the work
int i = ui.intValue()             // unsigned value assigned to i

Ответ 7

Если вы хотите использовать примитивные классы-оболочки, это будет работать, но все типы java по умолчанию подписаны.

public static void main(String[] args) {
    Integer i=5;
    Byte b = Byte.valueOf(i+""); //converts i to String and calls Byte.valueOf()
    System.out.println(b);
    System.out.println(Integer.valueOf(b));
}

Ответ 8

За исключением char, все остальные числовые типы данных в Java подписаны.

Как было сказано в предыдущем ответе, вы можете получить значение без знака, выполняя and операции с 0xFF. В этом ответе я собираюсь объяснить, как это происходит.

int i = 234;
byte b = (byte) i;
System.out.println(b);  // -22

int i2 = b & 0xFF;      
// This is like casting b to int and perform and operation with 0xFF

System.out.println(i2); // 234

Если ваша машина 32-разрядная, то для хранения значений типа данных int требуется 32-разрядная. byte нуждается только в 8 битах.

Переменная int i представлена в памяти следующим образом (как 32-разрядное целое число).

0{24}11101010

Тогда byte переменная b представляется как:

11101010

Поскольку byte не подписан, это значение представляет -22. (Найдите 2 дополнения, чтобы узнать больше о том, как представлять отрицательные целые числа в памяти)

Тогда, если вы приведете is к int оно все равно будет -22 потому что приведение сохраняет знак числа.

1{24}11101010

Приведенное 32-bit значение b выполняет and работает с 0xFF.

 1{24}11101010 & 0{24}11111111
=0{24}11101010

Тогда вы получите 234 в качестве ответа.

Ответ 9

в Яве 7

public class Main {
    public static void main(String[] args) {
        byte b =  -2;
        int i = 0 ;
        i = ( b & 0b1111_1111 ) ;
        System.err.println(i);
    }
}

результат: 254