人気ブログランキング |

符号付きbyteを符号なしbyteにしたい


byte[] address = InetAddress.getLocalHost().getHostAddress();
for( byte b : address )
  System.out.print(b + ".");


-64.-88.0.1.

ぼく「????」


※ 最後のピリオドは風物詩のようなものです。




今更感のあるエントリーですが。
結論だけ見たい方はこっち



まずJavaのbyte型は符号ありです。

Cでいうunsignedなんてものはないです。
※Java8から変換メソッドができたようですが。


なので最上位ビットが1だと負数扱いになってしまいます。


本来は「192.168.0.1」と出てほしいのです。以下のように。

signed -64 = 0b1100_0000 = 0xC0 = unsigned 192
signed -88 = 0b1101_1000 = 0xA8 = unsigned 168
signed 0 = 0b0000_0000 = 0x00 = unsigned 0
signed 1 = 0b0000_0001 = 0x01 = unsigned 1



これは最上位ビットが符号であることが原因なので、
最上位ビットも数値であることを示せばいいのです。

一番簡単なのは、変数をワイドニング変換(アップキャスト)することです


たとえば、intにしましょう。
そうすることで、数値的には以下のようになり、192.168~と出力されるはずです。
0000_0000_0000_0000_0000_0000_1100_0000


for( byte b : address )
  System.out.print((int)b + ".");


-64.-88.0.1.


そうはなりません。

ワイドニング変換の値埋めに使用されるのは符号ビットなので、
実際には 1111_1111_1111_1111_1111_1111_1100_0000 になります。


これでは困ります。
0000_0000_0000_0000_0000_0000_1100_0000になってほしいのです。



ということで、 000000FFとの AND を取りましょう。


1111_1111_1111_1111_1111_1111_1100_0000
0000_0000_0000_0000_0000_0000_1111_1111 )and
0000_0000_0000_0000_0000_0000_1100_0000

目的の値が取れそうです。


コードは以下のように。


for( byte b : address )
  System.out.print((b & 0xFF) + ".");

192.168.0.1.


できました。









そんなことより、こういう感じのループで最後の文字を消すうまい方法が知りたいです。


ほげ1:
StringBuilder sb = new StringBuilder();
for (byte b : ad) {
  sb.append(b & 0xFF);
  sb.append(".");
}
System.out.println(sb.substring(0, sb.length() - 1));


ほげ2:
for (int i = 0; i < address.length - 1; i++)
  System.out.print((address[i] & 0xFF) + ".");
System.out.println((address[address.length - 1] & 0xFF));



だれかスマートな方法教えてください。
by hsls | 2015-09-16 15:50 | 技術記事


<< weblogic.rjvm.P... WebLogicで組み込みEJ... >>