Ответ 1
Байт всегда подписан в Java. Вы можете получить его значение без знака с помощью двоичного кода и с 0xFF, но:
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
Мне нужно преобразовать число в беззнаковый байт. Число всегда меньше или равно 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
. Любые предложения?
Байт всегда подписан в Java. Вы можете получить его значение без знака с помощью двоичного кода и с 0xFF, но:
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
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 бит.
Если вам просто нужно преобразовать ожидаемое 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
.
Вызов Integer.toString(size)
преобразуется в представление char вашего целого числа, т.е. char '5'
. ASCII-представление этого символа - это значение 65.
Сначала нужно проанализировать строку до целочисленного значения, например. используя Integer.parseInt
, чтобы вернуть исходное значение int.
В качестве нижней строки для подписанного/беззнакового преобразования лучше оставить String
из изображения и использовать манипуляции с битами, как предлагает @JB.
Решение работает отлично (спасибо!), но если вы хотите избежать кастинга и оставить работу низкого уровня в 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. полезно для обработки двоичных форматов данных (например, форматов плоских сообщений и т.д.).
Обработка байтов и целых чисел без знака с помощью 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
Если вы хотите использовать примитивные классы-оболочки, это будет работать, но все типы 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));
}
За исключением 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
в качестве ответа.
в Яве 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