source

int를 부호 없는 바이트로 변환하고 되돌리는 방법

factcode 2022. 9. 28. 00:06
반응형

int를 부호 없는 바이트로 변환하고 되돌리는 방법

숫자를 부호 없는 바이트로 변환해야 합니다.숫자는 항상 255보다 작거나 같으므로 1바이트에 들어갑니다.

그 바이트를 그 숫자로 다시 변환해야 합니다.자바에서는 어떻게 하면 좋을까요?여러 가지 방법을 시도해 봤지만 소용이 없어요.제가 지금 하려는 일은 다음과 같습니다.

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

Java 8은 변환 기능을 제공합니다.byte로.int서명되지 않은 변환에 의해.Oracle의 JDK에서는 다음과 같이 구현됩니다.return ((int) x) & 0xff;HotSpot은 이 패턴을 최적화하는 방법을 이미 알고 있지만 다른 VM에 내장되어 있을 수 있습니다.더 중요한 것은, 사전에 알고 있을 필요는 없다는 것입니다.toUnsignedInt(foo)한다.

전체적으로 Java 8은 변환 방법을 제공합니다.byte그리고.short서명하지 않고int그리고.long,그리고.int서명하지 않고long. 변환 방법byte서명하지 않고shortJVM이 의도적으로 생략한 것은, 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.

제외하고charJava의 다른 모든 숫자 데이터 유형은 서명됩니다.

이전 답변에서 말했다으로서, 고객님께서는 이자를 극복하기 위해 부호 없는 가치를 얻을 수 있다.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비트가 필요합니다. byte8비트만 필요합니다.

int변수i는, 메모리내에서 다음과 같이 표시됩니다(32비트 정수).

0{24}11101010

그 다음에byte변수b는 다음과 같이 표시됩니다.

11101010

~하듯이byte는 서명되어 있습니다.이 값은-22(메모리에서 음의 정수를 표현하는 방법에 대해 자세히 알아보려면 2의 보수를 검색하십시오.)

그럼 캐스팅을 하면int여전히 그럴 것이다-22캐스팅은 숫자의 기호를 보존하기 때문입니다.

1{24}11101010

캐스트32-bit의 가치b수행하다and와의 작전.0xFF.

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

그럼 넌 얻을 수 있어234해답으로.

Integer.toString(size)call은 정수(즉 char)의 char 표현으로 변환됩니다.'5' 문자의 ASCII 표시는 값 65 입니다.

원래 int 값을 되돌리려면 예를 들어 를 사용하여 문자열을 먼저 정수 값으로 해석해야 합니다.

결론적으로, 서명된/서명되지 않은 변환의 경우 종료하는 것이 가장 좋습니다.String@가 제안하는 대로JB의 멤버입니다.

솔루션은 정상적으로 동작합니다(감사합니다). 그러나 캐스팅을 피하고 낮은 수준의 작업을 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();

특히 바이너리 데이터 형식(예: 플랫 메시지 형식 등)을 처리하는 데 유용합니다.

너무 늦었지만 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 doc에서 https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html byte라고 하고 있듯이 바이트는 필수 유형입니다.바이트 데이터 유형은 8비트 부호 2의 보완 정수입니다.

따라서 정수(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 확장 프리미티브 변환(expanding primitive conversion)(expanding 5.1.2)이 적용되어 다음 규칙에 의해 지정된 오퍼랜드 중 하나 또는 양쪽 오퍼랜드가 변환됩니다.

어느 하나의 피연산자가 double 유형인 경우 다른 피연산자는 double로 변환됩니다.

그렇지 않으면 어느 피연산자가 플로트 유형이면 다른 피연산자는 플로트로 변환됩니다.

그렇지 않으면 어느 하나의 오퍼랜드가 long 유형일 경우 다른 오퍼랜드는 long으로 변환됩니다.

그렇지 않으면 두 오퍼랜드가 int 유형으로 변환됩니다.

integrated type 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));
}

가독성 측면에서 나는 Guava를 선호한다.

  • UnsignedBytes.checkedCast(long)부호 있는 숫자를 부호 없는 바이트로 변환합니다.
  • UnsignedBytes.toInt(byte)인트

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

시험해보고 이해했어요.Java에서는 바이트가 부호화되어 있기 때문에, 1개의 부호 있는 바이트의 234는 -22, 바이너리에서는 "11101010"이고, 부호 있는 비트는 "1"을 가지고 있기 때문에, 음의 프레젠테이션 2의 보완과 함께, -22가 됩니다.또한 0xFF, 234~2바이트 부호(32비트)를 캐스트하여 모든 비트를 변경하지 않고 동작합니다.

이 문제를 해결하기 위해 String을 사용합니다.

int a = 14206;
byte[] b = String.valueOf(a).getBytes();
String c = new String(b);
System.out.println(Integer.valueOf(c));

출력은 14206 입니다.

언급URL : https://stackoverflow.com/questions/7401550/how-to-convert-int-to-unsigned-byte-and-back

반응형