Как конвертировать Int в беззнаковый байт и обратно - PullRequest
82 голосов
/ 13 сентября 2011

Мне нужно преобразовать число в беззнаковый байт.Число всегда меньше или равно 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.Есть предложения?

Ответы [ 9 ]

181 голосов
/ 13 сентября 2011

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

46 голосов
/ 18 марта 2015

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

В общей сложности Java 8 предоставляет методы для преобразования byte и short в беззнаковые int и longи int без знака long.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 * * * * * * * * * 10 * * * * * * * * * * 10 * * * * * 10 * * * 10 * * 10 * * 10 * * 10 * * 10 10 *байт, просто используйте приведение: (byte)someInt.Результирующее сужающее примитивное преобразование отбрасывает все, кроме последних 8 бит.

7 голосов
/ 11 июля 2013

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

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.

3 голосов
/ 13 сентября 2011

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

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

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

2 голосов
/ 03 мая 2012

Решение работает отлично (спасибо!), Но если вы хотите избежать приведения и оставить работу низкого уровня 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. полезно для обработки двоичных форматов данных (например, плоских форматов сообщений и т. д.)

1 голос
/ 09 мая 2019

За исключением 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 s без знака, это значение представляет -22. (Поиск дополнения 2, чтобы узнать больше о том, как представлять отрицательные целые числа в памяти)

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

1{24}11101010

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

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

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

1 голос
/ 20 ноября 2012

Обработка байтов и целых чисел без знака с помощью 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
0 голосов
/ 01 января 2018

в Яве 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

0 голосов
/ 13 сентября 2011

Если вы хотите использовать примитивные классы-обертки, это будет работать, но все типы 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));
}
...