Мне нужно преобразовать число в байт без знака. Число всегда меньше или равно 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
источник
0xFF
приводит к беззнаковому целому числу? Некоторое объяснение было бы действительно полезно.Java 8 обеспечивает
Byte.toUnsignedInt
преобразованиеbyte
вint
беззнаковое преобразование. В Oracle JDK это просто реализовано,return ((int) x) & 0xff;
поскольку HotSpot уже понимает, как оптимизировать этот шаблон, но он может быть встроен на других виртуальных машинах. Что еще более важно, не требуется никаких предварительных знаний, чтобы понять, чтоtoUnsignedInt(foo)
делает call to .В целом, Java 8 предоставляет методы для преобразования
byte
иshort
в беззнаковыйint
иlong
, иint
в беззнаковыйlong
. Метод преобразованияbyte
в беззнаковыйshort
был намеренно опущен, потому что JVM предоставляет только арифметические операцииint
и вlong
любом случае.Чтобы преобразовать Int обратно в один байт, просто использовать бросок:
(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)
новообращенном вызове в полукоксе представление вашего целого числа, т.е. полукокса'5'
. ASCII представление этого символа является значение 65.Вам нужно сначала разобрать строку до целочисленного значения, например, используя
Integer.parseInt
, чтобы вернуть исходное значение int.Подводя итог, для преобразования
String
со знаком / без знака лучше не использовать изображение и использовать битовые манипуляции, как предлагает @JB.источник
String sizeStr = Integer.toString(size); int sizeInt = Integer.parseInt(sizeStr); byte binaryByte = Byte.valueOf((byte) sizeInt);
String.getBytes()
значения ASCII символов, содержащихся в тексте, а не числовые значения цифр. Вам нужно разобрать строку в числовое значение, как я намекнул выше.Решение работает нормально (спасибо!), Но если вы хотите избежать кастинга и оставить низкоуровневую работу 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. полезен для обработки двоичных форматов данных (например, форматов плоских сообщений и т. д.)
источник
Кроме того
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
приведете is к, это все равно будет,-22
потому что приведение сохраняет знак числа.1{24}11101010
Приведенное
32-bit
значениеb
выполненияand
операции с0xFF
.1{24}11101010 & 0{24}11111111 =0{24}11101010
Тогда вы получите
234
ответ.источник
Несмотря на то, что уже слишком поздно, я хотел бы высказать свое мнение по этому поводу, поскольку это может прояснить, почему решение, данное JB Nizet, работает. Я наткнулся на эту небольшую проблему, работая над синтаксическим анализатором байтов и преобразованием строк сам. Когда вы копируете интегральный тип большего размера в интегральный тип меньшего размера, как говорится в этом java-документе, это происходит:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3 Сужающее преобразование целого числа со знаком в целочисленный тип T просто отбрасывает все, кроме n наименьшего порядка битов, где n - количество битов, используемых для представления типа T. Помимо возможной потери информации о величине числового значения, это может привести к тому, что знак результирующего значения будет отличаться от знака входного значения. .
Вы можете быть уверены, что байт является интегральным типом, как говорится в этом java-документе https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html byte: байтовый тип данных - это 8-битные подписанные два дополнять целое число.
Таким образом, в случае преобразования целого числа (32 бита) в байт (8 бит) вы просто копируете последние (наименее значимые 8 бит) этого целого числа в заданную байтовую переменную.
int a = 128; byte b = (byte)a; // Last 8 bits gets copied System.out.println(b); // -128
Вторая часть истории касается того, как унарные и бинарные операторы Java продвигают операнды. https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 Расширяющееся примитивное преобразование (§5.1.2) применяется для преобразования одного или обоих операндов, как указано по следующим правилам:
Если один из операндов имеет тип double, другой преобразуется в double.
В противном случае, если один из операндов имеет тип float, другой преобразуется в float.
В противном случае, если один из операндов имеет тип long, другой преобразуется в long.
В противном случае оба операнда преобразуются в тип int.
Будьте уверены, если вы работаете с целым типом int и / или ниже, он будет повышен до int.
// byte b(0x80) gets promoted to int (0xFF80) by the & operator and then // 0xFF80 & 0xFF (0xFF translates to 0x00FF) bitwise operation yields // 0x0080 a = b & 0xFF; System.out.println(a); // 128
Я тоже почесал в затылке :). Здесь есть хороший ответ rgettman. Побитовые операторы в Java только для целых и длинных?
источник
Если вы хотите использовать примитивные классы-оболочки, это сработает, но все типы 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)); }
источник
Обработка байтов и целых чисел без знака с помощью 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 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
источник