Java로 부호없는 바이트를 만들 수 있습니까?


185

부호없는 바이트를 부호없는 바이트로 변환하려고합니다. 문제는 내가받는 데이터가 서명되지 않았고 Java가 부호없는 바이트를 지원하지 않기 때문에 데이터를 읽을 때 부호있는 것으로 취급합니다.

Stack Overflow에서 얻은 다음 솔루션으로 변환하려고했습니다.

public static int unsignedToBytes(byte a)
{
    int b = a & 0xFF;
    return b;
}

그러나 다시 바이트로 변환되면 동일한 부호있는 데이터가 표시됩니다. 이 데이터를 매개 변수로 바이트 만 허용하는 Java 함수의 매개 변수로 사용하려고하므로 다른 데이터 형식을 사용할 수 없습니다. 이 문제를 어떻게 해결할 수 있습니까?


2
구아바 : UnsignedBytes.toint (바이트 값)
jacktrades

20
java.lang.Byte.toUnsignedInt (바이트 값);
themarketka

답변:


107

귀하의 질문을 이해하지 못했습니다.

방금 이것을 시도하고 바이트 -12 (서명 값)에 대해 정수 244 (부호없는 바이트 값과 동일하지만으로 입력)를 반환했습니다 int.

  public static int unsignedToBytes(byte b) {
    return b & 0xFF;
  }

  public static void main(String[] args) {
    System.out.println(unsignedToBytes((byte) -12));
  }

당신이하고 싶은 일입니까?

자바는 같은 244 표현할 수 없습니다 byte겠습니까 C.에 위에서 양의 정수 표현으로, 값이 Byte.MAX_VALUE(127)는 같은 타 정수 유형을 사용해야합니다 short, int또는 long.


1
byte b = (byte)unsignedToBytes((byte) -12); 이제 b를 인쇄 해보십시오
Jigar 조시

101
왜 이것을 정답으로 받아들였습니까? 그것은 당신이 질문에 언급 한 방법과 정확히 동일합니다-바이트를 부호없는 정수로 변환하십시오.
Adamski

1
때로는 부호있는 값, 때로는 부호없는 것을 갖는 것이 중요하므로 아마도이 대답을 수락 한 이유 일 것입니다. (byte) (b & 0xff)는 의미가 없지만 (byte) (Math.min ((b & 0xff) * 2, 255))는 의미가 있습니다. 예를 들어 컴퓨터 그래픽에서는 픽스를 바이트가 두 배 더 밝습니다. :-)
iirekm

3
byteToUnsigned라고 할 수도 있습니다
Hernán Eche

195

프리미티브가 Java로 서명되었다는 사실은 메모리 / 전송에서 표현되는 방식과 관련이 없습니다. 바이트는 8 비트에 불과하며 서명 된 범위로 해석하는지 여부는 귀하에게 달려 있습니다. "this is signed"또는 "this is unsigned"라고 말하는 마술 깃발은 없습니다.

프리미티브가 서명되면 Java 컴파일러는 +127보다 높은 값을 바이트 (또는 -128보다 작은)에 할당하지 못하게합니다. 그러나 이것을 달성하기 위해 int (또는 short)를 다운 캐스팅하는 것을 막을 수는 없습니다.

int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200)
byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention)

/*
 * Will print a negative int -56 because upcasting byte to int does
 * so called "sign extension" which yields those bits:
 * 1111 1111 1111 1111 1111 1111 1100 1000 (-56)
 *
 * But you could still choose to interpret this as +200.
 */
System.out.println(b); // "-56"

/*
 * Will print a positive int 200 because bitwise AND with 0xFF will
 * zero all the 24 most significant bits that:
 * a) were added during upcasting to int which took place silently
 *    just before evaluating the bitwise AND operator.
 *    So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`.
 * b) were set to 1s because of "sign extension" during the upcasting
 *
 * 1111 1111 1111 1111 1111 1111 1100 1000 (the int)
 * &
 * 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF)
 * =======================================
 * 0000 0000 0000 0000 0000 0000 1100 1000 (200)
 */
System.out.println(b & 0xFF); // "200"

/*
 * You would typically do this *within* the method that expected an 
 * unsigned byte and the advantage is you apply `0xFF` only once
 * and than you use the `unsignedByte` variable in all your bitwise
 * operations.
 *
 * You could use any integer type longer than `byte` for the `unsignedByte` variable,
 * i.e. `short`, `int`, `long` and even `char`, but during bitwise operations
 * it would get casted to `int` anyway.
 */
void printUnsignedByte(byte b) {
    int unsignedByte = b & 0xFF;
    System.out.println(unsignedByte); // "200"
}

5
많은 작업에서는 차이가 없지만 일부 작업에서는 차이가 없습니다. 어느 쪽이든 바이트를 부호없는 것으로 사용하거나 부호없는 char을 사용할 수 있습니다.
피터 로리

62
음수로 배열에 액세스하는 것은 중요하지 않습니다.
Stefan

3
@ 스테판 (Stefan)-나는 그들이 와이어에서 표현되는 방식과 관련이 없다는 것을 의미했습니다.
Adamski

6
어느 것이 질문과 관련이 없습니다. 그가 바이트 매개 변수 만 받아들이는 함수에 전달해야한다고 언급 했으므로 날씨에 상관없이 우리는 이것을 유니콘의 바이트 표현으로 해석합니다. Java는 항상 부호있는 숫자로 취급하므로이 함수가 매개 변수를 색인으로 사용하는 경우에는 문제가 될 수 있습니다. 그러나 공정하게 말하면 다른 상위 2 개의 답변도 하향 조정했습니다. 왜냐하면 그들은 질문에 대답하지 않기 때문입니다.
Stefan

2
@Stefan +1 당신을 위해. 바이트를 사용하여 256 요소의 배열에 액세스하는 경우 절대적으로 관련이 있습니다. 모든 사람들이 자바 나 C #을로 이동하기 전에 C와 C ++를 배우기 시작해야하는 이유 입증하는 좋은 예입니다
잔 루카 Ghettini

46

Java에서 부호없는 바이트로 작업하기위한 전체 안내서 :

Java에서 부호없는 바이트

(이 답변의 출처.)


Java 언어는 unsigned키워드 와 같은 것을 제공하지 않습니다 . byte언어 사양에 따른 -128 사이의 값을 나타냅니다 - 예를 들어 127, A는 경우 byte에 캐스팅 int부호 및 사용과 같은 첫 번째 비트 해석합니다 자바 부호 확장을 .

즉, byte단순히 8 비트로 볼 수 없으며 그 비트를 0에서 255 사이의 값으로 해석 할 수 없습니다. 다른 사람의 방법에 대해 해석을 강요하기 위해 할 수있는 것은 없습니다. 메소드가 a를 승인하면 byte, 달리 명시되지 않는 한 해당 메소드는 -128에서 127 사이의 값을 승인합니다.

다음은 사용자 편의를위한 유용한 변환 / 조작 몇 가지입니다.

int로 /에서 변환

// From int to unsigned byte
int i = 200;                    // some value between 0 and 255
byte b = (byte) i;              // 8 bits representing that value

// From unsigned byte to int
byte b = 123;                   // 8 bits representing a value between 0 and 255
int i = b & 0xFF;               // an int representing the same value

또는 Java 8 이상인 경우을 사용하십시오 Byte.toUnsignedInt.

파싱 ​​/ 포맷

가장 좋은 방법은 위의 전환을 사용하는 것입니다.

// Parse an unsigned byte
byte b = (byte) Integer.parseInt("200");

// Print an unsigned byte
System.out.println("Value of my unsigned byte: " + (b & 0xFF));

산술

2의 보수 표현은 덧셈, 뺄셈 및 곱셈에 대해 "그냥 작동합니다":

// two unsigned bytes
byte b1 = (byte) 200;
byte b2 = (byte) 15;

byte sum  = (byte) (b1 + b2);  // 215
byte diff = (byte) (b1 - b2);  // 185
byte prod = (byte) (b2 * b2);  // 225

Division은 피연산자를 수동으로 변환해야합니다.

byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));

1
'char'는 숫자를 나타내지 않습니다.
로그 오프

26
간단히 말해서 : 당신은 틀 렸습니다 .
aioobe

36

Java에는 원시 부호없는 바이트가 없습니다. 일반적인 것은 더 큰 유형으로 캐스팅하는 것입니다.

int anUnsignedByte = (int) aSignedByte & 0xff;

int에 캐스트해야합니까?
nich

암시 적 캐스트 일 수 있지만 어느 쪽이든 캐스트됩니다. 그리고 그 캐스트는 서명 된 확장을 수행합니다. 그리고 그것은 문제입니다. 명시 적 캐스트를 수행하면 적어도 이것이 발생하고 있음을 알 수 있습니다.
foo


4

참고로, 인쇄하고 싶다면

byte b = 255;
System.out.println((b < 0 ? 256 + b : b));

6
왜 그렇게 복잡한가? println(b & 0xff)충분하다
phuclv

0

당신이 이런 것을 찾고 있다고 생각한다면.

public static char toUnsigned(byte b) {
    return (char) (b >= 0 ? b : 256 + b);
}

0

Adamski가 가장 좋은 답변을 제공했지만 완전히 완성되지는 않았으므로 자세한 내용을 설명하는 그의 답변을 읽으십시오.

부호없는 바이트를 전달해야하는 시스템 기능이있는 경우 부호없는 바이트를 자동으로 부호없는 바이트로 처리하므로 부호있는 바이트를 전달할 수 있습니다.

따라서 시스템 함수에 4 바이트가 필요하면 (예 : 192 168 0 1을 부호없는 바이트로) -64 -88 0 1을 전달할 수 있으며, 함수에 전달하면 서명되지 않으므로 함수는 여전히 작동합니다. .

그러나 일부 플랫폼의 호환성을 위해 시스템 기능이 클래스 뒤에 숨겨져 있기 때문에이 문제가 발생하지는 않을 것입니다.

이 작업을보고 싶다면 부호있는 바이트를 파일에 쓰고 부호없는 바이트로 다시 읽습니다.


1
부호있는 바이트 또는 부호없는 바이트와 같은 것은 없습니다.
Vlastimil Ovčáčík

예제에서 바이트를 정확히 쓰고 읽고 있었습니까?
Vlastimil Ovčáčík

0

당신은 또한 수:

public static int unsignedToBytes(byte a)
{
    return (int) ( ( a << 24) >>> 24);
}    

설명:

의 말을하자 a = (byte) 133;

메모리에 다음과 같이 저장됩니다 : "1000 0101"(16 진수로 0x85)

따라서 그 표현은 부호없는 = 133, 부호있는 = -123 (2의 보수로)을 번역합니다.

<< 24

왼쪽으로 24 비트를 왼쪽으로 이동하면 결과 는 다음과 같이 4 바이트 정수가됩니다.

"10000101 00000000 00000000 00000000"(또는 16 진수로 "0x85000000")

우리는

(a << 24) >>> 24

오른쪽 24 비트에서 다시 이동하지만 선행 0으로 채워집니다. 결과는 다음과 같습니다.

"00000000 00000000 00000000 10000101"(또는 16 진수로 "0x00000085")

그리고 이것은 133과 같은 부호없는 표현입니다.

캐스트하려고 a = (int) a; 하면 2의 보수 표현 바이트를 유지하고 2의 보수로 int로 저장합니다.

(int) "10000101"---> "11111111 11111111 11111111 10000101"

그리고 그것은 다음과 같이 번역됩니다 : -123


2
2019 년에는 불필요합니다. 그냥 사용하십시오 java.lang.Byte.toUnsignedInt(byte value). Java 8을 아직 사용하지 않는 경우 최대한 빨리 업그레이드하십시오. Java 7 및 이전 버전은 수명이 다되었습니다.
Stephen C

0

이 데이터를 매개 변수로 바이트 만 허용하는 Java 함수의 매개 변수로 사용하려고합니다.

2 ^ 32-1보다 큰 값을 전달하려는 정수를 허용하는 함수와 크게 다르지 않습니다.

함수의 정의 및 문서화 방법에 따라 달라집니다. 세 가지 가능성을 볼 수 있습니다.

  1. 함수가 바이트를 부호없는 값으로 취급한다고 명시 적으로 문서화 할 수 있습니다.이 경우 함수는 예상대로 수행해야하지만 잘못 구현 된 것으로 보입니다. 정수의 경우 함수는 아마도 매개 변수를 부호없는 정수로 선언하지만 바이트의 경우 불가능합니다.

  2. 이 인수의 값이 0보다 크거나 같아야한다고 문서화 할 수 있습니다.이 경우 함수를 잘못 사용하고 (범위를 벗어난 매개 변수를 전달 함) 의도 한 것보다 더 많은 기능을 수행해야합니다. 하다. 일정 수준의 디버깅 지원을 사용하면 함수에서 예외가 발생하거나 어설 션이 실패 할 수 있습니다.

  3. 문서는 아무 것도 말할 수 없으며,이 경우 음수 매개 변수는 음수 매개 변수이며 그 의미가 있는지 여부는 함수의 기능에 따라 다릅니다. 이것이 의미가 없다면 아마도 함수는 실제로 (2)로 정의 / 문서화되어야합니다. 이것이 명백하지 않은 방식으로 의미가있는 경우 (예를 들어, 음이 아닌 값은 배열로 색인화하는 데 사용되고 음의 값은 배열의 끝에서 다시 색인하는 데 사용되므로 -1은 마지막 요소를 의미 함) 의미와 나는 그것이 당신이 원하는대로되지 않을 것으로 기대합니다.


흠, 나는 바이트의 부호에 관한 또 다른 질문에 대한 답장을 방금 올렸다고 생각하지만, 여기에도 여전히 조금 관련이 있다고 생각합니다 ...
Kevin Martin

-1

부호있는 바이트를 전달해야하는 함수가있는 경우 부호없는 바이트를 전달하면 어떻게해야합니까?

다른 데이터 유형을 사용할 수없는 이유는 무엇입니까?

비정상적으로 변환을 간단하거나 전혀 수행하지 않고 바이트를 부호없는 바이트로 사용할 수 있습니다. 그것은 모두 그것이 어떻게 사용되는지에 달려 있습니다. 당신은 당신이 그것으로 무엇을했는지 명시해야합니다.


-1

Java가 언어에 부호없는 바이트를 포함하지 않았다는 것이 성가신 것처럼 보일지 모르지만 (b & 0xFF) 간단한 조작으로 (희소 한) 바이트 (서명 된) 바이트 b에 대한 부호없는 값을 생성하기 때문에 실제로 큰 문제는 아닙니다. 실제로 필요한 상황. 비트는 실제로 변경되지 않으며 해석 만합니다 (예 : 값에 대한 일부 수학 연산을 수행 할 때만 중요 함).


다른 사람의 답변을보고 답변이 가장 좋거나 도움이된다고 생각하십니까? 거의 설명하지 않고 댓글에 추가
Jubin Patel

8
그것은 아니다 드문 당신이 그것을 건너 적이 없다해서. 프로토콜을 구현하면이 백만 번 나올 것입니다. 성가신 것은 바이트를 다루는 대부분의 유스 케이스가 부호없는 바이트 (숫자가 아니라 바이트이기 때문에)를 처리하려고한다는 것입니다. 미친 점은 모든 비트 단위 연산이 int로 변환한다는 것입니다. 즉, "음수"값이 확장되면 완전히 다른 값이됩니다. 예, 항상 마스킹하여 문제를 해결할 수는 있지만 시간과 프로세서를 낭비하고 잊어 버리면 실제로 모호한 버그가 발생합니다.
Thor84no

Thor84no에 동의합니다. 바이트는 숫자가 아니며 부호가 없어야합니다. 반면에 숫자가 아니기 때문에 + 및-연산자를 사용하거나 사용해서는 안됩니다. 비트 연산자 만 사용하면 정상적으로 작동하고 다른 쪽에서는 시프트 연산자가 원하는대로 작동하지 않으며 실제로 java는 시프트 된 바이트를 int로 승격시킵니다.
user1708042

1
@ VlastimilOvčáčík이 경우 말 그대로 불가능합니다. 그것은 교묘 한 일입니다. x & 0xFF필요한 곳이면 어디든지 반복 하거나 behaveLikeAnUnsignedByte(x)어디에서나 같은 것을 반복하십시오 . 이것은 바이트 값 또는 바이트 배열을 사용하여 부호가없는 모든 단일 장소에 필요 하며이 반복을 피할 수있는 방법은 없습니다. 당신은 할 수 읽고 바이트 변수에 단 하나의 참조 바이트 값을 기록하는 프로토콜의 구현을 작성합니다. 당신의 단순한 견해는 왜 그들이 그것을 고치려고하지 않았는지 설명 할 수 있습니다.
Thor84no

-1

Java에는 부호없는 바이트가 없지만 바이트를 표시하려면 할 수 있습니다.

int myInt = 144;

byte myByte = (byte) myInt;

char myChar = (char) (myByte & 0xFF);

System.out.println("myChar :" + Integer.toHexString(myChar));

산출:

myChar : 90

자세한 정보 는 Java로 16 진 / 바이트 값을 표시하는 방법을 확인하십시오 .


직접 정의 할 필요가 없습니다. java.lang.Byte.toUnsignedInt(byte value);이를 위해 존재합니다.
Alexander-Reinstate Monica

-2

Java의 제한 사항에 따라 부호없는 바이트는 현재 데이터 형식 형식에서 거의 불가능합니다. 구현중인 것에 대해 다른 언어의 다른 라이브러리를 찾은 다음 JNI를 사용하여 호출 할 수 있습니다 .


나는 그것을 부호있는 바이트로 저장하고 싶지 않다고 생각합니다. 그는 부호있는 바이트로 수신하고 있으며 완벽하게 유효한 int로 저장하려고합니다. 그의 문제는 입력을받는 곳이 0에서 255 사이의 값을 바이트로 나타내는 것이지만 Java는 부호있는 바이트를 지원하지 않기 때문에 2를 보수 부호있는 값으로 해석한다는 것입니다.
Zac

-2

예, 아니오 나는이 문제로 파고 들었다. 내가 이것을 이해하는 것처럼 :

사실은 java가 interger -128에서 127까지 서명했다는 것입니다.

public static int toUnsignedInt(byte x) {
    return ((int) x) & 0xff;
}

예를 들어 부호없는 -12 부호있는 숫자를 추가하면 244가됩니다. 그러나 부호있는 숫자로 다시 사용할 수 있으면 부호있는 숫자로 다시 이동해야하며 다시 -12가됩니다.

java 바이트에 244를 추가하려고하면 outOfIndexException이 발생합니다.

건배..


3
직접 정의 할 필요가 없습니다. java.lang.Byte.toUnsignedInt(byte value);이를 위해 존재합니다.
Alexander-Reinstate Monica

-3

Java에서 부호없는 바이트를 원하면 관심있는 숫자에서 256을 빼십시오 .2의 보수를 생성합니다. 부호없는 바이트의 원하는 숫자 인 음수 값으로 를 합니다.

예:

int speed = 255; //Integer with the desired byte value
byte speed_unsigned = (byte)(speed-256);
//This will be represented in two's complement so its binary value will be 1111 1111
//which is the unsigned byte we desire.

leJOS 를 사용 하여 NXT 브릭 을 프로그래밍 할 때 이러한 더러운 핵을 사용해야 합니다.


255의 이진수 값도 1111 1111이므로 빼기가 필요하지 않습니다.
Nick White

@NickWhite, 이진입니다. 그러나 자바는 255가 11111111이 아닌 2의 보수를 사용합니다.
XapaJIaMnu

죄송하지만 이건 잘못입니다. 몇 가지 실험을 해보십시오. 의 값 speed_unsigned은 부호가 있습니다. 그것을 인쇄하고보십시오. (그리고 - 256여기서 달성 한 것은 없습니다.)
Stephen C
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.