Java 코드 바이트를 16 진수로 변환하려면


184

바이트 배열이 있습니다. 해당 배열의 각 바이트 문자열을 해당하는 16 진수 값으로 변환하고 싶습니다.

Java에서 바이트 배열을 16 진수로 변환하는 함수가 있습니까?


2
Java에서 바이트 배열이라고하는 것을 다른 언어에서는 바이트 문자열이라고합니다 (예 : docs.racket-lang.org/guide/bytestrings.html )
Patrick Favre

답변:


311
    byte[] bytes = {-1, 0, 1, 2, 3 };
    StringBuilder sb = new StringBuilder();
    for (byte b : bytes) {
        sb.append(String.format("%02X ", b));
    }
    System.out.println(sb.toString());
    // prints "FF 00 01 02 03 "

또한보십시오

  • java.util.Formatter 통사론
    • %[flags][width]conversion
      • 플래그 '0'-결과가 0으로 채워집니다.
      • 2
      • 변환 'X'-결과는 16 진수 정수 (대문자)로 형식이 지정됩니다

질문의 텍스트를 보면 이것이 요청 된 것일 수도 있습니다.

    String[] arr = {"-1", "0", "10", "20" };
    for (int i = 0; i < arr.length; i++) {
        arr[i] = String.format("%02x", Byte.parseByte(arr[i]));
    }
    System.out.println(java.util.Arrays.toString(arr));
    // prints "[ff, 00, 0a, 14]"

여기에 몇 가지 대답이 사용됩니다 Integer.toHexString(int). 이것은 가능하지만 약간의 경고가 있습니다. 매개 변수가이므로 기호 확장이 포함 된 인수에 int대해 확장 기본 변환이 수행됩니다 byte.

    byte b = -1;
    System.out.println(Integer.toHexString(b));
    // prints "ffffffff"

byteJava로 서명 된 8 비트 는 32 비트로 확장됩니다 int. 이 부호 확장을 효과적으로 실행 취소하기 위해 bytewith를 마스크 할 수 있습니다 0xFF.

    byte b = -1;
    System.out.println(Integer.toHexString(b & 0xFF));
    // prints "ff"

사용의 또 다른 문제 toHexString는 0으로 채워지지 않는다는 것입니다.

    byte b = 10;
    System.out.println(Integer.toHexString(b & 0xFF));
    // prints "a"

두 가지 요소를 결합하면 String.format솔루션이 더 선호됩니다.

참고 문헌


@Vivek : "엄청나게 큰 가치"란 무엇입니까? 입력은 무엇이며 출력은 무엇입니까?
polygenelubricants

다시 설명하겠습니다. 배열에 바이트 문자열 모음이 있습니다. 하지만 내가해야 할 일은 각 바이트를 따로 분석하는 것입니다. 따라서 전체 배열에서 작업하고 싶지 않지만 한 번에 개별 바이트 문자열, 즉 해당 배열의 구성 요소 중 하나입니다. 혼동은 " 정렬". 이제 아래 코드에서 "byte bv = 10; String hexString = Integer.toHexString (bv);"CAse 1 (Byte Receved : 68 Hex Output : : 44) Case : 2 (Byte Recieved : -46 Hex Output : : ffffffd2) ......... 왜 일부 값에 대해 예기치 않은 결과가 발생합니까?
Vivek

1
@Vivek : 사용에 대한 내 대답을 읽으십시오 toHexString. 로 마스크해야합니다 . & 0xFFInteger.toHexString(-46 & 0xFF)입니다 "d2".
polygenelubricants

@polygenelubricants : 감사합니다. 마지막으로 코드가 제대로 작동하는 것 같습니다. toHexString 함수를 사용해도 안전합니까? 또는 접근 방식에 허점이있을 수 있습니다.
Vivek

1
@Vivek : "안전"하므로주의 byte해서 & 0xFF매번 값을 숨겨야합니다 . format위 의 솔루션은 실제로 인수로 사용하는 것에 따라 마스킹이 필요할 수 있습니다.
polygenelubricants

65

기존 답변 중 왜 그들의 접근 방식이 효과가 있는지 설명하지 않기 때문에 게시하고 있습니다.이 문제에 정말 중요하다고 생각합니다. 경우에 따라 제안 된 솔루션이 불필요하게 복잡하고 미묘 해 보일 수 있습니다. 설명하기 위해 상당히 간단한 접근 방식을 제공하지만 그 이유를 설명하는 데 도움이되도록 좀 더 자세히 설명 하겠습니다.

우선, 우리는 무엇을하려고합니까? 바이트 값 (또는 바이트 배열)을 ASCII로 16 진수 값을 나타내는 문자열로 변환하려고합니다. 따라서 첫 번째 단계는 Java에서 바이트가 무엇인지 정확히 찾는 것입니다.

바이트 데이터 형식은 8 비트 부호있는 2의 보수 정수 입니다. 최소값은 -128이고 최대 값은 127입니다 (포함). 바이트 데이터 유형은 메모리 절약이 실제로 중요한 큰 배열로 메모리를 저장하는 데 유용 할 수 있습니다. 또한 그들의 한계가 코드를 명확하게하는 데 도움이되는 int 대신 사용될 수도 있습니다. 변수의 범위가 제한되어 있다는 사실은 문서 형태로 작용할 수 있습니다.

이것은 무엇을 의미 하는가? 몇 가지 : 첫째, 가장 중요한 것은 8 비트로 작업하고 있음을 의미 합니다. 예를 들어 숫자 2를 0000 0010으로 쓸 수 있습니다. 그러나 2의 보수이므로 다음과 같이 음수 2를 씁니다 : 1111 1110. 또한 16 진수로 변환하는 것은 매우 간단합니다. 즉, 각 4 비트 세그먼트를 16 진수로 직접 변환하기 만하면됩니다. 이 체계에서 음수를 이해하려면 먼저 2의 보수를 이해해야합니다. 2의 보수를 아직 이해하지 못하면 여기에서 훌륭한 설명을 읽을 수 있습니다. http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html


일반적으로 2의 보수를 16 진수로 변환

숫자가 2의 보수에 들어가면 16 진수로 변환하는 것은 간단합니다. 일반적으로 바이너리에서 16 진수로 변환하는 것은 매우 간단하며 다음 두 예에서 볼 수 있듯이 2의 보수에서 16 진수로 직접 이동할 수 있습니다.

예 1 : 2를 16 진수로 변환하십시오.

1) 먼저 2의 보수에서 2를 이진수로 변환하십시오.

2 (base 10) = 0000 0010 (base 2)

2) 이제 바이너리를 16 진수로 변환하십시오.

0000 = 0x0 in hex
0010 = 0x2 in hex

therefore 2 = 0000 0010 = 0x02. 

예 2 : -2 (2의 보수)를 16 진으로 변환하십시오.

1) 먼저 2의 보수에서 -2를 이진수로 변환하십시오.

-2 (base 10) = 0000 0010 (direct conversion to binary) 
               1111 1101 (invert bits)
               1111 1110 (add 1)
therefore: -2 = 1111 1110 (in two's complement)

2) 이제 16 진수로 변환하십시오.

1111 = 0xF in hex
1110 = 0xE in hex

therefore: -2 = 1111 1110 = 0xFE.


자바에서 이것을하기

이제 개념을 다루었으므로 간단한 마스킹 및 시프트를 통해 원하는 것을 달성 할 수 있습니다. 이해해야 할 핵심은 변환하려는 바이트가 이미 2의 보수에 있다는 것입니다. 이 변환을 직접 수행하지 마십시오. 나는 이것이이 문제에 대한 혼란의 주요 지점이라고 생각합니다. 다음 바이트 배열을 예로 들어 보겠습니다.

byte[] bytes = new byte[]{-2,2};

위의 16 진수로 수동으로 변환했지만 Java로 어떻게 할 수 있습니까? 방법은 다음과 같습니다.

1 단계 : 계산을 보유 할 StringBuffer를 만듭니다.

StringBuffer buffer = new StringBuffer();

2 단계 : 상위 비트를 분리하여 16 진수로 변환 한 후 버퍼에 추가

이진수 1111 1110이 주어지면 우선 상위 비트를 4 씩 시프트 한 다음 나머지 숫자를 0으로 만들어 분리 할 수 ​​있습니다. 논리적으로 이것은 간단하지만 Java (및 많은 언어)의 구현 세부 사항은 부호 확장으로 인해 주름을 유발합니다. 기본적으로 바이트 값을 이동하면 Java는 먼저 값을 정수로 변환 한 다음 부호 확장을 수행합니다. 따라서 1111 1110 >> 4는 0000 1111이 될 것으로 예상되지만 실제로 Java에서는 2의 보수 0xFFFFFFFF로 표시됩니다!

따라서 우리의 예로 돌아갑니다 :

1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)

그런 다음 마스크로 비트를 분리 할 수 ​​있습니다.

1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex. 

Java에서는이 모든 작업을 한 번에 수행 할 수 있습니다.

Character.forDigit((bytes[0] >> 4) & 0xF, 16);

forDigit 함수는 전달한 숫자를 16 진수 0-F 집합에 매핑합니다.

3 단계 : 다음으로 하위 비트를 분리해야합니다. 원하는 비트가 이미 올바른 위치에 있으므로 마스크를 마스킹 할 수 있습니다.

1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.  

이전과 마찬가지로 Java에서는이 모든 작업을 한 번에 수행 할 수 있습니다.

Character.forDigit((bytes[0] & 0xF), 16);

이 모든 것을 종합하면 for 루프로 수행하고 전체 배열을 변환 할 수 있습니다.

for(int i=0; i < bytes.length; i++){
    buffer.append(Character.forDigit((bytes[i] >> 4) & 0xF, 16));
    buffer.append(Character.forDigit((bytes[i] & 0xF), 16));
}

바라건대이 설명은 인터넷에서 찾을 수있는 많은 예제에서 무슨 일이 일어나고 있는지 궁금해하는 사람들에게 더 명확하게 해줍니다. 잘만되면 나는 중대한 오류를 만들지 않았지만 제안과 수정은 매우 환영합니다!


4
가장 좋은 답변! 16 진수 문자열을 바이트로 변환하는 대칭 구현은 다음 Character.digit()과 같이 사용합니다 .(byte) ((Character.digit(str.charAt(0), 16) << 4) + Character.digit(str.charAt(1), 16))
ericbn

21

빠른 내가 아직이 일을 발견했습니다 방법은 다음과 같다 :

private static final String    HEXES    = "0123456789ABCDEF";

static String getHex(byte[] raw) {
    final StringBuilder hex = new StringBuilder(2 * raw.length);
    for (final byte b : raw) {
        hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
    }
    return hex.toString();
}

~보다 50 배 빠릅니다 String.format. 테스트하고 싶다면 :

public class MyTest{
    private static final String    HEXES        = "0123456789ABCDEF";

    @Test
    public void test_get_hex() {
        byte[] raw = {
            (byte) 0xd0, (byte) 0x0b, (byte) 0x01, (byte) 0x2a, (byte) 0x63,
            (byte) 0x78, (byte) 0x01, (byte) 0x2e, (byte) 0xe3, (byte) 0x6c,
            (byte) 0xd2, (byte) 0xb0, (byte) 0x78, (byte) 0x51, (byte) 0x73,
            (byte) 0x34, (byte) 0xaf, (byte) 0xbb, (byte) 0xa0, (byte) 0x9f,
            (byte) 0xc3, (byte) 0xa9, (byte) 0x00, (byte) 0x1e, (byte) 0xd5,
            (byte) 0x4b, (byte) 0x89, (byte) 0xa3, (byte) 0x45, (byte) 0x35,
            (byte) 0xd6, (byte) 0x10,
        };

        int N = 77777;
        long t;

        {
            t = System.currentTimeMillis();
            for (int i = 0; i < N; i++) {
                final StringBuilder hex = new StringBuilder(2 * raw.length);
                for (final byte b : raw) {
                    hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
                }
                hex.toString();
            }
            System.out.println(System.currentTimeMillis() - t); // 50
        }

        {
            t = System.currentTimeMillis();
            for (int i = 0; i < N; i++) {
                StringBuilder hex = new StringBuilder(2 * raw.length);
                for (byte b : raw) {
                    hex.append(String.format("%02X", b));
                }
                hex.toString();
            }
            System.out.println(System.currentTimeMillis() - t); // 2535
        }

    }
}

편집 : 그냥 빨리 단지 릴 무언가를 발견하고 그 한 줄에 보유하고 있지만 호환되지 JRE (9)와 자신의 위험에 사용

import javax.xml.bind.DatatypeConverter;

DatatypeConverter.printHexBinary(raw);

2
DatatypeConverter는 더 이상 Java 9에서 사용할 수 없습니다. 위험한 것은 Java 1.8 이전 버전 (소스 설정이 이전 인 Java 9)에서는 컴파일되지만 Java 9에서는 런타임 예외가 발생한다는 것입니다.
Stephen M -on strike-

나는 두 번째 @StephenMs가 포인트 : jre9와 함께이 사용하는면 ClassNotFound 예외와 충돌합니다
패트릭 파브르

실제로 printHexBinary jdk의 src.zip에서 소스 코드 메소드 를 간단히 추출 할 수 있는데, 이는 첫 번째 메소드보다 1 배 빠릅니다.
과일

1
HEXES 상수에 대해 char 배열을 사용하는 경우 String 및 charAt () 대신 ~ 20 % 더 빠른 속도를 얻습니다.
Dyorgio

15

이 방법으로 시도하십시오 :

byte bv = 10;
String hexString = Integer.toHexString(bv);

배열 다루기 (잘 이해하면) :

byte[] bytes = {9, 10, 11, 15, 16};
StringBuffer result = new StringBuffer();
for (byte b : bytes) {
    result.append(String.format("%02X ", b));
    result.append(" "); // delimiter
}
return result.toString();

polygenelubricants가 언급했듯이 (정확한 방법으로 음수를 처리 String.format()하기 Integer.toHexString()때문에) 정답 입니다.


2
예를 들어 try와 같이 확장됩니다 -1.
polygenelubricants

바이트 bv = 10; 문자열 hexString = 정수 .toHexString (bv); 이것은 Firne으로 작동하는 것 같습니다. 배열의 모든 요소에 개별적으로 적용 할 수 있습니다. 다른 코드 (array 다루기)는 너무 큰 값을 돌려줍니다. 그 reaason 무엇 bw 수 있습니까?
Vivek

@Vivek bv16 진수 문자 하나를 반환 하기 때문입니다 . 나머지 코드는 16 진수 문자열을 반환합니다 . 델리 미터로 코드를 변경하여 지금 이해할 수 있습니다.
0x2D9A3

@Bar : with 를 실행 취소하여 부호 확장을 취소 Integer.toHexString하면 여전히 사용할 수 있습니다 . byte0xFF
polygenelubricants

사례 1 (바이트 수신 : 68 16 진수 출력 : : 44) 사례 : 2 (바이트 수신 : -46 16 진수 출력 : : ffffffd2) 음의 바이트 배열의 경우 예기치 않은 출력 값이 나타납니다 ... 어떻게 처리합니까?
Vivek

13

최선의 해결책은 다음과 같은 불량한 단일 라이너입니다.

String hex=DatatypeConverter.printHexBinary(byte[] b);

여기에 언급 된 바와 같이


4
DatatypeConverter는 더 이상 Java 9에서 사용할 수 없습니다. 위험한 것은 Java 1.8 이전 버전 (소스 설정이 이전 인 Java 9)에서는 컴파일되지만 Java 9에서는 런타임 예외가 발생한다는 것입니다.
Stephen M -on strike-

jdk9에 없다고 말하면 슬프다. new BigInteger(byteArray).toString(16)그런 다음 갈 길입니다. 그 성능 문제가 있습니까 ??
prayagupd

아마도 perf 문제는 아니지만 BigInteger와 같은 숫자에는 의미가 없으므로 선행 0을 놓칠 수 있습니다.
Friso

그것은 여전히 자바 9 문서 에있는 것처럼 보입니다. 그래서 내가 말할 수있는 것에서 여전히 사용하는 것이 좋습니다.
Brad Parks

여기에 설명 된대로 java9에 사용하는 것이 좋지만 향후 Java 릴리스에서 제거 될 것이라고 생각 합니다. 버전 2.3.0 부터 '새로운'독립형 jaxb 모듈과 함께 계속 사용할 수 있습니다 .
Lynx

11

바이트를 명확하게 복구 할 수 있도록 일정한 너비의 16 진수 표현을 원한다면 (예 : 0A대신) 다음을 A시도하십시오 format().

StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
    result.append(String.format("%02X", bb));
}
return result.toString();

11

다음 byte[]을 사용하여 16 진 문자열 로 변환 하는 간단하고 간단한 방법 BigInteger:

import java.math.BigInteger;

byte[] bytes = new byte[] {(byte)255, 10, 20, 30};
String hex = new BigInteger(1, bytes).toString(16);
System.out.println(hex); // ff0a141e

작동 원리

내장 시스템 클래스 java.math.BigInteger클래스 ( java.math.BigInteger )는 2 진 및 16 진 데이터와 호환됩니다.

  • 그것에 BigInteger(signum=1, byte[])의해 큰 정수를 생성 하는 생성자 가 있습니다 byte[](첫 번째 매개 변수 설정 signum=1 음수 바이트를 올바르게 처리하기 위해)
  • BigInteger.toString(16)큰 정수를 16 진 으로 변환하는 데 사용 문자열
  • 16 진수 사용을 구문 분석하려면 new BigInteger("ffa74b", 16)선행 0을 올바르게 처리하지 않습니다.

16 진 결과에서 선행 0 을 원할 경우 크기를 확인하고 필요한 경우 누락 된 0을 추가하십시오.

if (hex.length() % 2 == 1)
    hex = "0" + hex;

노트

Java가 " 설계에 의해 손상됨 "이고 데이터 유형이 바이트를 보유하지 않고 부호있는 작은 정수 [-128 ... 127] 이므로 new BigInteger(1, bytes)대신 대신을 사용하십시오 . 첫 번째 바이트가 음수이면 음수 큰 정수를 전달한다고 가정합니다. 첫 번째 매개 변수로 전달하십시오 (new BigInteger(bytes)byteBigInteger1signum=1 ) .

16 진수에서 16 진수로byte[] 의 변환 은 까다로워집니다. 때로는 생성 된 출력에 선행 제로가 들어가고 다음과 같이 정리해야합니다.

byte[] bytes = new BigInteger("ffa74b", 16).toByteArray();
if (bytes[0] == 0) {
    byte[] newBytes = new byte[bytes.length - 1];
    System.arraycopy(bytes, 1, newBytes, 0, newBytes.length);
    bytes = newBytes;
}

마지막으로 byte[]몇 개의 선행 0이 있으면 손실됩니다.


1
선행 바이트의 16 진수 값이 16보다 작은 경우 홀수의 16 진 문자가 포함 된 문자열도 얻게됩니다.
Alex Jorgenson

8

외부 라이브러리를 사용하고 싶다면 org.apache.commons.codec.binary.Hex클래스에는 encodeHexa를 사용 byte[]하고 a 를 반환하는 메소드 가 있습니다 char[]. 이 방법은 형식 옵션보다 훨씬 빠르며 변환 세부 정보를 캡슐화합니다. 또한 함께 제공 decodeHex반대의 변환을위한 방법.


4
더 쉬운 방법은 내장 함수 javax.xml.bind.DatatypeConverter / parseHexBinary 및 printHexBinary를 사용하는 것입니다. 참조 stackoverflow.com/questions/9655181/...
앨런 톰슨

2
이 옵션에 +1 Hex는 또한 byte []를 받아서 String을 리턴하는 encodeHexString 메소드를 가지고 있습니다.
Mingjiang Shi

것을 잊지 마세요 javax네임 스페이스는 항상 사용할 수 없습니다.
Mene

7

Bouncy Castle Provider 라이브러리 의 방법을 사용할 수 있습니다 .

org.bouncycastle.util.encoders.Hex.toHexString(byteArray);

탄력 성 암호화 패키지는 Java의 암호화 알고리즘 구현입니다. 이 jar에는 JDK 1.5에서 JDK 1.8까지의 Bouncy Castle Cryptography API에 대한 JCE 제공자 및 경량 API가 포함되어 있습니다.

메이븐 의존성 :

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.60</version>
</dependency>

또는 Apache Commons Codec에서 :

org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);

Apache Commons Codec 패키지에는 Base64 및 Hexadecimal과 같은 다양한 형식의 간단한 인코더 및 디코더가 포함되어 있습니다. 코덱 패키지는 널리 사용되는 이러한 인코더 및 디코더 외에도 음성 인코딩 유틸리티 모음을 유지 관리합니다.

메이븐 의존성 :

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>

예, 이것이 가장 좋은 솔루션 이지만 외부 라이브러리가 필요합니다 : Apache Commons Codec ( mvnrepository.com/artifact/commons-codec/commons-codec/1.11 ) 또는 BouncyCastle Provider ( mvnrepository.com/artifact/org.bouncycastle/bcprov- jdk15on / 1.60 )
Svetlin Nakov

5

이것은 지금까지 가장 빨리 실행되는 것으로 밝혀진 코드입니다. 32ms 길이의 109015 바이트 배열에서 23ms로 실행했습니다. VM에서 실행했기 때문에 베어 메탈에서 더 빠르게 실행될 것입니다.

public static final char[] HEX_DIGITS =         {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

public static char[] encodeHex( final byte[] data ){
    final int l = data.length;
    final char[] out = new char[l<<1];
    for( int i=0,j=0; i<l; i++ ){
        out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4];
        out[j++] = HEX_DIGITS[0x0F & data[i]];
    }
    return out;
}

그럼 당신은 할 수 있습니다

String s = new String( encodeHex(myByteArray) );

3
BigInteger n = new BigInteger(byteArray);
String hexa = n.toString(16));

작동하지 않음 : BigInteger(byteArrayOf(-1, 2, 3, 4, 5)).toString(16)반품"-fdfcfbfb"
Martin Vysny

올바른 결과입니다. 바이트 '-1', '2'... '5'로 작업하고 있습니다. 리터럴 '-1', '2'... '5'로 작업하려는 경우 바이트 값에 시각화 ( unicode.org ) 가 없습니다 . 문자열 값으로 작업해야합니다.
Wender

잘못된 결과입니다. Java 바이트 값이 -1 (int) 255이므로 Java 바이트가 서명되므로 실제로 0xFF (와 동일 )이므로 결과는이어야합니다 FF02030405. 위의 @Jerinaw 솔루션을 시도하면 올바른 출력이 인쇄되는 것을 볼 수 있습니다. 아래의 Svetlin Nakov 솔루션도 참조하십시오.
Martin Vysny

2

다음은 바이트를 16 진수로 변환하는 간단한 함수입니다.

   private static String convertToHex(byte[] data) {
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; i++) {
        int halfbyte = (data[i] >>> 4) & 0x0F;
        int two_halfs = 0;
        do {
            if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));
            halfbyte = data[i] & 0x0F;
        } while(two_halfs++ < 1);
    }
    return buf.toString();
}

2

다른 사람들은 일반적인 경우를 다루었습니다. 그러나 알려진 형식의 바이트 배열 (예 : MAC 주소)이있는 경우 다음을 수행 할 수 있습니다.

byte[] mac = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };

String str = String.format("%02X:%02X:%02X:%02X:%02X:%02X",
                           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 

1

잔뜩 만들기 (및 파괴) String퍼포먼스가 문제인 경우 인스턴스를 것은 좋은 방법이 아닙니다.

이러한 장황한 (중복) 인수 확인 문은 무시하십시오 if. 그것은 (또 다른) 교육 목적입니다.

풀 메이븐 프로젝트 : http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/

부호화...

/**
 * Encodes a single nibble.
 *
 * @param decoded the nibble to encode.
 *
 * @return the encoded half octet.
 */
protected static int encodeHalf(final int decoded) {

    switch (decoded) {
        case 0x00:
        case 0x01:
        case 0x02:
        case 0x03:
        case 0x04:
        case 0x05:
        case 0x06:
        case 0x07:
        case 0x08:
        case 0x09:
            return decoded + 0x30; // 0x30('0') - 0x39('9')
        case 0x0A:
        case 0x0B:
        case 0x0C:
        case 0x0D:
        case 0x0E:
        case 0x0F:
            return decoded + 0x57; // 0x41('a') - 0x46('f')
        default:
            throw new IllegalArgumentException("illegal half: " + decoded);
    }
}


/**
 * Encodes a single octet into two nibbles.
 *
 * @param decoded the octet to encode.
 * @param encoded the array to which each encoded nibbles are written.
 * @param offset the offset in the array.
 */
protected static void encodeSingle(final int decoded, final byte[] encoded,
                                   final int offset) {

    if (encoded == null) {
        throw new IllegalArgumentException("null encoded");
    }

    if (encoded.length < 2) {
        // not required
        throw new IllegalArgumentException(
            "encoded.length(" + encoded.length + ") < 2");
    }

    if (offset < 0) {
        throw new IllegalArgumentException("offset(" + offset + ") < 0");
    }

    if (offset >= encoded.length - 1) {
        throw new IllegalArgumentException(
            "offset(" + offset + ") >= encoded.length(" + encoded.length
            + ") - 1");
    }

    encoded[offset] = (byte) encodeHalf((decoded >> 4) & 0x0F);
    encoded[offset + 1] = (byte) encodeHalf(decoded & 0x0F);
}


/**
 * Decodes given sequence of octets into a sequence of nibbles.
 *
 * @param decoded the octets to encode
 *
 * @return the encoded nibbles.
 */
protected static byte[] encodeMultiple(final byte[] decoded) {

    if (decoded == null) {
        throw new IllegalArgumentException("null decoded");
    }

    final byte[] encoded = new byte[decoded.length << 1];

    int offset = 0;
    for (int i = 0; i < decoded.length; i++) {
        encodeSingle(decoded[i], encoded, offset);
        offset += 2;
    }

    return encoded;
}


/**
 * Encodes given sequence of octets into a sequence of nibbles.
 *
 * @param decoded the octets to encode.
 *
 * @return the encoded nibbles.
 */
public byte[] encode(final byte[] decoded) {

    return encodeMultiple(decoded);
}

디코딩...

/**
 * Decodes a single nibble.
 *
 * @param encoded the nibble to decode.
 *
 * @return the decoded half octet.
 */
protected static int decodeHalf(final int encoded) {

    switch (encoded) {
        case 0x30: // '0'
        case 0x31: // '1'
        case 0x32: // '2'
        case 0x33: // '3'
        case 0x34: // '4'
        case 0x35: // '5'
        case 0x36: // '6'
        case 0x37: // '7'
        case 0x38: // '8'
        case 0x39: // '9'
            return encoded - 0x30;
        case 0x41: // 'A'
        case 0x42: // 'B'
        case 0x43: // 'C'
        case 0x44: // 'D'
        case 0x45: // 'E'
        case 0x46: // 'F'
            return encoded - 0x37;
        case 0x61: // 'a'
        case 0x62: // 'b'
        case 0x63: // 'c'
        case 0x64: // 'd'
        case 0x65: // 'e'
        case 0x66: // 'f'
            return encoded - 0x57;
        default:
            throw new IllegalArgumentException("illegal half: " + encoded);
    }
}


/**
 * Decodes two nibbles into a single octet.
 *
 * @param encoded the nibble array.
 * @param offset the offset in the array.
 *
 * @return decoded octet.
 */
protected static int decodeSingle(final byte[] encoded, final int offset) {

    if (encoded == null) {
        throw new IllegalArgumentException("null encoded");
    }

    if (encoded.length < 2) {
        // not required
        throw new IllegalArgumentException(
            "encoded.length(" + encoded.length + ") < 2");
    }

    if (offset < 0) {
        throw new IllegalArgumentException("offset(" + offset + ") < 0");
    }

    if (offset >= encoded.length - 1) {
        throw new IllegalArgumentException(
            "offset(" + offset + ") >= encoded.length(" + encoded.length
            + ") - 1");
    }

    return (decodeHalf(encoded[offset]) << 4)
           | decodeHalf(encoded[offset + 1]);
}


/**
 * Encodes given sequence of nibbles into a sequence of octets.
 *
 * @param encoded the nibbles to decode.
 *
 * @return the encoded octets.
 */
protected static byte[] decodeMultiple(final byte[] encoded) {

    if (encoded == null) {
        throw new IllegalArgumentException("null encoded");
    }

    if ((encoded.length & 0x01) == 0x01) {
        throw new IllegalArgumentException(
            "encoded.length(" + encoded.length + ") is not even");
    }

    final byte[] decoded = new byte[encoded.length >> 1];

    int offset = 0;
    for (int i = 0; i < decoded.length; i++) {
        decoded[i] = (byte) decodeSingle(encoded, offset);
        offset += 2;
    }

    return decoded;
}


/**
 * Decodes given sequence of nibbles into a sequence of octets.
 *
 * @param encoded the nibbles to decode.
 *
 * @return the decoded octets.
 */
public byte[] decode(final byte[] encoded) {

    return decodeMultiple(encoded);
}

1

이것은 매우 빠른 방법입니다. 외부 라이브러리가 필요하지 않습니다.

final protected static char[] HEXARRAY = "0123456789abcdef".toCharArray();

    public static String encodeHexString( byte[] bytes ) {

        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEXARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEXARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

1

바이트 문자열의 의미를 정확히 알 수는 없지만 바이트에서 문자열로의 변환과 그 반대로의 변환이 있습니다. 물론 공식 문서에는 더 많은 내용이 있습니다.

Integer intValue = 149;

해당 바이트 값은 다음과 같습니다.

Byte byteValue = intValue.byteValue(); // this will convert the rightmost byte of the intValue to byte, because Byte is an 8 bit object and Integer is at least 16 bit, and it will give you a signed number in this case -107

바이트 변수에서 정수 값을 다시 가져옵니다.

Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer

바이트 및 정수에서 16 진수 문자열까지 :
이것이 내가하는 방법입니다.

Integer anInt = 149
Byte aByte = anInt.byteValue();

String hexFromInt = "".format("0x%x", anInt); // This will output 0x95
String hexFromByte = "".format("0x%x", aByte); // This will output 0x95

바이트 배열을 16 진수 문자열로 변환 :
내가 아는 한 일부 배열 내부의 모든 Object요소를 다른 요소의 요소로 변환하는 간단한 기능은 없으므로 Object직접해야합니다. 다음 기능을 사용할 수 있습니다 :

바이트 []에서 문자열로 :

    public static String byteArrayToHexString(byte[] byteArray){
        String hexString = "";

        for(int i = 0; i < byteArray.length; i++){
            String thisByte = "".format("%x", byteArray[i]);
            hexString += thisByte;
        }

        return hexString;
    }

그리고 16 진 문자열에서 바이트 []로 :

public static byte[] hexStringToByteArray(String hexString){
    byte[] bytes = new byte[hexString.length() / 2];

    for(int i = 0; i < hexString.length(); i += 2){
        String sub = hexString.substring(i, i + 2);
        Integer intVal = Integer.parseInt(sub, 16);
        bytes[i / 2] = intVal.byteValue();
        String hex = "".format("0x%x", bytes[i / 2]);
    }

    return bytes;
}  

너무 늦었지만 이것이 다른 사람들을 도울 수 있기를 바랍니다.)


1

빠른 방법이 있습니다.

    private static final String[] hexes = new String[]{
        "00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
        "10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
        "20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
        "30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
        "40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
        "50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
        "60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
        "70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
        "80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
        "90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
        "A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
        "B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
        "C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
        "D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
        "E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
        "F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
    };

    public static String byteToHex(byte b) {
        return hexes[b&0xFF];
    }

1
추악하지만 아마도 매우 효율적입니다. :-)
Rich S

1

다른 답변과 마찬가지로 String.format()및 을 사용하는 것이 좋습니다 BigInteger. 그러나 바이트 배열 을 2의 보수 이진 표현 (기호 및 가능한 16 진수 값 범위의 불완전한 사용) 대신 빅 엔디안 이진 표현 으로 해석하려면 BigInteger (byte [] val이 아닌 BigInteger ( int signum, byte [] 크기)를 사용하십시오 ) .

예를 들어, 길이가 8 인 바이트 배열의 경우 다음을 사용하십시오.

String.format("%016X", new BigInteger(1,bytes))

장점 :

  • 선행 제로
  • 부호 없음
  • 내장 함수 만
  • 한 줄의 코드

불리:

  • 더 효율적인 방법이있을 수 있습니다

예:

byte[] bytes = new byte[8];
Random r = new Random();
System.out.println("big-endian       | two's-complement");
System.out.println("-----------------|-----------------");
for (int i = 0; i < 10; i++) {
    r.nextBytes(bytes);
    System.out.print(String.format("%016X", new BigInteger(1,bytes)));
    System.out.print(" | ");
    System.out.print(String.format("%016X", new BigInteger(bytes)));
    System.out.println();
}

출력 예 :

big-endian       | two's-complement
-----------------|-----------------
3971B56BC7C80590 | 3971B56BC7C80590
64D3C133C86CCBDC | 64D3C133C86CCBDC
B232EFD5BC40FA61 | -4DCD102A43BF059F
CD350CC7DF7C9731 | -32CAF338208368CF
82CDC9ECC1BC8EED | -7D3236133E437113
F438C8C34911A7F5 | -BC7373CB6EE580B
5E99738BE6ACE798 | 5E99738BE6ACE798
A565FE5CE43AA8DD | -5A9A01A31BC55723
032EBA783D2E9A9F | 032EBA783D2E9A9F
8FDAA07263217ABA | -70255F8D9CDE8546

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.