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


92

数値を符号なしバイトに変換する必要があります。数値は常に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ます。助言がありますか?


私もこの方法を試しました:crazysquirrel.com/computing/java/basics/…-機能しません。
darksky

回答:


200

バイトは常にJavaで署名されます。ただし、2進数で0xFFを使用して符号なしの値を取得できます。

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

まだ65歳になります。なぜですか?
darksky

1
欲しい数をバイトに格納しています。Javaは、それを符号なしの数値ではなく、符号付きの数値と見なします。しかし、すべてのビットはあたかもそれが符号なしの数であるかのように同じです。文字列をバイトに変換することは、もう1つの無関係な質問です。新しい質問で個別に投稿してください。
JBニゼット2009

1
getIntを使用してintを取得し、intをバイトとして変換します。intはintです。それがどこから来たかは問題ではありません。
JBニゼット2011

18
なぜビット単位で0xFF符号なし整数になるのですか?いくつかの説明は本当に役に立ちます。
user462455

2
Java 8は同じメソッドを使用します:public static int toUnsignedInt(byte x){return((int)x)&0xff; }
Daniel

55

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

合計では、Java(登録商標)8を変換する方法を提供byteし、short符号なしにint及びlong、そしてint符号なしにlong。変換する方法byte、符号なしにはshort故意省略 JVMのみで演算を提供するため、intそしてlongとにかく。

intをバイトに戻すには、キャストを使用します(byte)someInt。結果のナローイングプリミティブ変換では、最後の8ビット以外はすべて破棄されます。


7

予想される8ビット値をsigned intからunsigned値に変換する必要があるだけの場合は、単純なビットシフトを使用できます。

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

また、bytetype は使用できないことに注意してください。これを使用すると、他の回答者によって言及されているように、署名された値になります。8ビットの符号なし値を表すために使用できる最小のプリミティブ型はですshort


3

Integer.toString(size)あなたの整数、すなわち文字の文字表現に呼び出し変換'5'。その文字のASCII表現は値65です。

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

String結論として、符号付き/符号なし変換の場合は、@ JBが示唆するように、図を省略してビット操作を使用するのが最善です。


このように?(まだここに65を取得)String sizeStr = Integer.toString(size); int sizeInt = Integer.parseInt(sizeStr); byte binaryByte = Byte.valueOf((byte) sizeInt);
darksky

@Nayefc、私はあなたのコメントを書いていただけのように私の答えを更新しました:-)
ペーテルTörök

わかりました、ありがとう!何らかの理由で、それでも65を出力します。これは何を意味するのでしょうか?それがちょうど65を示している場合、実際にバイトに格納されているものは取得できません。また、私の質問を確認してください、私はそれを編集し、文字列変換に関するセクションを追加しました:)
darksky

@Nayefc も、数字の数値ではなく、テキストに含まれる文字のString.getBytes() ASCII値を生成します。上記で示唆したように、文字列を数値に解析する必要があります。
ペーテルTörök

1
@Nayefc、それは実際にはまったく異なる質問です。そしてそれはうまくいくはずです。変換の実際の入力と出力、およびケースを再現するための完全なコードを含む、新しい質問を作成します。
ペーテルTörök

3

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

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


3

を除いて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

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

あなたはキャスト場合、でありint、それはまだだろう-22鋳物は数値の符号を保持しているため。

1{24}11101010

キャストされた32-bit値はb、でのand操作を実行し0xFFます。

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

その後、あなた234は答えとして得ます。


1

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

遅すぎますが、JB Nizetによって提供されたソリューションが機能する理由が明らかになる可能性があるため、これについて私の意見を述べたいと思います。私はバイトパーサーで作業しているこの小さな問題に出会い、自分で文字列変換を行いました。このjava docによると、大きなサイズの整数型から小さなサイズの整数型にコピーすると、次のようになります。

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 バイトを示しているので、バイトが整数型であることを確認でき ます:バイトデータ型は8ビットの符号付き2補数の整数。

したがって、整数(32ビット)をバイト(8ビット)にキャストする場合、その整数の最後(最下位8ビット)を指定のバイト変数にコピーするだけです。

int a = 128;
byte b = (byte)a; // Last 8 bits gets copied
System.out.println(b);  // -128

ストーリーの第2部では、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のビット単位演算子?


0

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

-1

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.