web-dev-qa-db-ja.com

Intを符号なしバイトに変換して戻す方法

数値を符号なしバイトに変換する必要があります。数値は常に255以下であるため、1バイトに収まります。

また、そのバイトをその数値に戻す必要があります。 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に変換します。助言がありますか?

83
darksky

バイトは常にJavaで署名されます。ただし、次のように0xFFでバイナリANDを実行すると、符号なしの値を取得できます。

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

Java 8は、 Byte.toUnsignedInt を提供して、byteを符号なし変換によりintに変換します。 OracleのJDKでは、これはreturn ((int) x) & 0xff;として単純に実装されます。これは、HotSpotがこのパターンを最適化する方法を既に理解しているためですが、他のVMに組み込まれる可能性があります。さらに重要なことは、toUnsignedInt(foo)の呼び出しが何をするかを理解するために事前の知識は必要ありません。

合計で、Java 8は、byteshortを符号なしのintlongに、およびintを符号なしのlongに変換するメソッドを提供します。 byteを符号なしshortに変換する方法は 意図的に省略 でした。これは、JVMがintおよびlongの演算のみを提供するためです。

Intをバイトに戻すには、キャストを使用します:(byte)someInt。結果の 縮小プリミティブ変換 は、最後の8ビットを除くすべてを破棄します。

48
Jeffrey Bosboom

予想される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です。

7
dm78

Integer.toString(size)呼び出しは、整数のchar表現、つまりchar '5'に変換します。その文字の ASCII表現 は値65です。

最初に文字列を解析して整数値に戻す必要があります。 Integer.parseInt を使用して、元のint値を取得します。

結論として、符号付き/符号なしの変換では、Stringを画像から除外し、@ JBが示唆するようにビット操作を使用するのが最善です。

3
Péter Török

ソリューションは正常に機能します(ありがとう!)が、キャストを避けて低レベルの作業を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();

特にバイナリデータ形式(フラットメッセージ形式など)の処理に役立ちます。

2
Gregor

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
1
pgrandjean

charを除き、Javaの他のすべての数値データ型は署名されます。

前の回答で述べたように、0xFFand操作を実行すると、符号なしの値を取得できます。この回答では、それがどのように起こるかを説明します。

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

bytesは符号なしなので、この値は-22を表します。 (2の補数を検索して、メモリ内の負の整数を表す方法の詳細をご覧ください)

キャストがintである場合、キャストは数値の符号を保持するため、-22のままです。

1{24}11101010

キャストされた32-bitbの値は、0xFFand操作を実行します。

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

次に、234を答えとして取得します。

1
Ramesh-X

プリミティブラッパークラスを使用する場合、これは機能しますが、すべての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));
}
0
Romeo