Java에서 바이트 배열에 일부 데이터를 저장하고 싶습니다. 기본적으로 숫자 당 최대 2 바이트를 사용할 수있는 숫자입니다.
정수를 2 바이트 길이의 바이트 배열로 변환하거나 그 반대로 변환하는 방법을 알고 싶습니다. 인터넷에서 많은 솔루션을 찾았지만 대부분 코드에서 일어나는 일을 설명하지 않습니다. 실제로 이해하지 못하는 많은 변화가 있기 때문에 기본 설명에 감사드립니다.
Java에서 바이트 배열에 일부 데이터를 저장하고 싶습니다. 기본적으로 숫자 당 최대 2 바이트를 사용할 수있는 숫자입니다.
정수를 2 바이트 길이의 바이트 배열로 변환하거나 그 반대로 변환하는 방법을 알고 싶습니다. 인터넷에서 많은 솔루션을 찾았지만 대부분 코드에서 일어나는 일을 설명하지 않습니다. 실제로 이해하지 못하는 많은 변화가 있기 때문에 기본 설명에 감사드립니다.
답변:
java.nio
네임 스페이스 에있는 클래스, 특히을 사용하십시오 ByteBuffer
. 그것은 당신을 위해 모든 일을 할 수 있습니다.
byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1
ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }
ByteBuffer
.
wrap
와 를 의미하는 경우 allocate
추상 클래스의 인스턴스를 반환하지 않습니다 ByteBuffer
.
Char
, Short
, Int
. 나는 매 4 바이트로 채울 수 있고 매번 네 번째를 버릴 수 있다고 가정하지만 오히려 그렇지 않습니다.
byte[] toByteArray(int value) {
return ByteBuffer.allocate(4).putInt(value).array();
}
byte[] toByteArray(int value) {
return new byte[] {
(byte)(value >> 24),
(byte)(value >> 16),
(byte)(value >> 8),
(byte)value };
}
int fromByteArray(byte[] bytes) {
return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, |
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
return ((bytes[0] & 0xFF) << 24) |
((bytes[1] & 0xFF) << 16) |
((bytes[2] & 0xFF) << 8 ) |
((bytes[3] & 0xFF) << 0 );
}
부호있는 바이트를 int로 패킹 할 때 각 바이트는 산술 승격 규칙 (JLS, 변환 및 승격에 설명 됨)으로 인해 32 비트 (0 확장이 아닌)로 확장되므로 마스크 해제해야합니다.
Joshua Bloch와 Neal Gafter의 Java Puzzlers ( "모든 바이트에서 큰 기쁨")에 설명 된 흥미로운 퍼즐이 있습니다. 바이트 값을 int 값과 비교할 때 바이트는 int로 부호 확장되고이 값은 다른 int와 비교됩니다.
byte[] bytes = (…)
if (bytes[0] == 0xFF) {
// dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}
16 비트 부호없는 정수 유형 인 char을 제외하고 모든 숫자 유형은 Java로 서명됩니다.
& 0xFF
불필요 하다고 생각합니다 .
& 0xFF
JVM이 부호있는 바이트를 비트 세트로 정수로 변환하도록 지시하기 때문에 s가 필요 하다고 생각합니다 . 그렇지 않으면 바이트 -1 (0xFF)이 int -1 (0xFFFFFFFF)로 바뀝니다. 나는 틀릴 수 있고, 그것이 아프더라도 일을 더 명확하게 만듭니다.
byte b = 0; b |= 0x88; System.out.println(Integer.toString(b, 16)); //Output: -78 System.out.println(Integer.toString(b & 0xFF, 16)); //Output: 88
byte
0xFF로 (으로 int
), JVM은 캐스팅됩니다 byte
에 int
로 확장 1 또는 0 확장 된 하여 첫 번째 비트 선도에 따라. Java 에는 부호없는 바이트 가 없으며 byte
항상 부호가 있습니다.
ByteBuffer.getInt()
: Reads the next four bytes at this buffer's current position
, 첫 번째 4 바이트 구문 분석됩니다, 당신이 원하는 무엇을하지 않아야한다.
가변 길이 바이트에 BigInteger를 사용할 수도 있습니다. 필요에 따라 long, int 또는 short로 변환 할 수 있습니다.
new BigInteger(bytes).intValue();
또는 극성을 나타 내기 위해 :
new BigInteger(1, bytes).intValue();
바이트를 다시 얻으려면 :
new BigInteger(bytes).toByteArray()
intValueExact
하지intValue
기본 구현은 다음과 같습니다.
public class Test {
public static void main(String[] args) {
int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
byte[] output = new byte[input.length * 2];
for (int i = 0, j = 0; i < input.length; i++, j+=2) {
output[j] = (byte)(input[i] & 0xff);
output[j+1] = (byte)((input[i] >> 8) & 0xff);
}
for (int i = 0; i < output.length; i++)
System.out.format("%02x\n",output[i]);
}
}
내용을 이해하기 위해이 WP 기사를 읽을 수 있습니다 : http://en.wikipedia.org/wiki/Endianness
위의 소스 코드가 출력 34 12 78 56 bc 9a
됩니다. 처음 2 바이트 ( 34 12
)는 첫 번째 정수 등을 나타냅니다. 위의 소스 코드는 작은 엔디안 형식의 정수를 인코딩합니다.
이것이 int로 캐스팅하는 가장 좋은 모드라고 생각합니다.
public int ByteToint(Byte B){
String comb;
int out=0;
comb=B+"";
salida= Integer.parseInt(comb);
out=out+128;
return out;
}
첫 번째 바이트를 문자열로 변환
comb=B+"";
다음 단계는 int로 변환됩니다.
out= Integer.parseInt(comb);
그러나 바이트는이 이유로 인해 -128에서 127까지의 분노에 해당합니다. 범위 0에서 255까지 사용하는 것이 더 좋다고 생각하면됩니다.
out=out+256;