Java에서 바이트 배열을 16 진수 문자열로 변환하는 방법은 무엇입니까?


649

16 진수로 채워진 바이트 배열이 있고 인쇄 할 수없는 요소가 많기 때문에 쉬운 방법으로 인쇄하는 것은 무의미합니다. 내가 필요한 것은 다음과 같은 형태의 정확한 16 진수 코드입니다.3a5f771c


12
먼저 시도해보고 당신이 가진 것을 보여주십시오. 당신은 잃을 것이없고 모두 얻을 것입니다. Integer에는 toHexString(...)이것이 당신이 찾고있는 것이라면 도움이 될 수 있는 방법이 있습니다. 또한 코드 문자열을 String.format(...)사용하여 깔끔한 서식 트릭을 수행 할 수 있습니다 %2x.
호버 크래프트 가득한 뱀장어


"내가 필요한 것은 3a5f771c ... 형식의 정확한 16 진 코드입니다."-정확한 양식을 요청했지만 정확한 예를 제공하지 않았습니다. 제공 한 내용으로 진행하여 처음 4 바이트를 문자열 로 변환 한 다음 줄임표를 문자열로 연결하십시오.
jww

1
Java 8에서 스트림을 사용하면 다음과 같이 간단하게 구현할 수 있습니다. static String byteArrayToHex (byte [] a) {return IntStream.range (0, a.length) .mapToObj (i-> String.format ( "% 02x ", a [i])) .reduce ((acc, v)-> acc +" "+ v) .get (); }
tibetty

답변:


901

토론에서 여기에 , 특히 대답이 내가 현재 사용하는 기능은 다음과 같습니다

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(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] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}

내 자신의 작은 벤치 마크 (천만 번, 256 바이트 천만 번)는 다른 대안보다 훨씬 빠르며 긴 배열의 절반에 달합니다. 내가 얻은 대답과 비교하여, 논의에서 제안한대로 비트 단위 연산으로 전환하면 긴 배열의 시간을 약 20 % 단축했습니다. (편집 : 대안보다 빠르면 토론에서 제공되는 대체 코드를 의미합니다. 성능은 매우 유사한 코드를 사용하는 Commons Codec와 같습니다.)

Java 9 컴팩트 문자열과 관련하여 2k20 버전 :

private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
    byte[] hexChars = new byte[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars, StandardCharsets.UTF_8);
}

266
방금 표준 배포의 일부인 javax.xml.bind.DataTypeConverter를 찾았습니다 . Google이 이런 종류의 문제를 겪을 때 왜 이것이 나타나지 않습니까? String printHexBinary(byte[])및 등 유용한 도구가 많이 있습니다 byte[] parseHexBinary(String). printHexBinary그러나이 답변의 기능보다 훨씬 (2 배) 느립니다. (소스를 확인했습니다 stringBuilder. parseHexBinary배열을 사용합니다.) 실제로 대부분의 경우 충분히 빠르며 이미 가지고있을 것입니다.
maybeWeCouldStealAVan 1

75
Android에는 DataTypeConverter가 없으므로 답변에 +1
Vaiden

7
@maybeWeCouldStealAVan : JDK 7은 이제 오픈 소스입니다. 성능 향상을 위해 패치를 제출해야합니다 printHexBinary.
kevinarpe

3
@maybeWeCouldStealAVan 이것이 어떻게 작동하는지 설명해 주시겠습니까? 나는 대부분을 따르지만 실제로 코드를 사용할 때 일어나는 일을 이해하는 것을 좋아합니다. 감사!
jjNford

24
javax.xml.bind.DataTypeConverterJava 11에서 제거되었습니다.
Impaler

421

아파치 코 몬즈 코덱 라이브러리는이 진수 작업의 바로 이런 종류의 작업을 수행하는 클래스.

import org.apache.commons.codec.binary.Hex;

String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );

12
@cytinus-내 downvote는 4 개월 전에 발생했기 때문에 내가 생각하고있는 것을 완전히 확신하지는 못했지만 아마도 라이브러리 크기에 반대하고 있었을 것입니다. 이것은 프로그램 내의 작은 기능입니다. 그렇게 큰 라이브러리를 프로젝트에 추가 할 필요가 없습니다.
ArtOfWarfare 5

6
@ArtOfWarefare 동의합니다. 대신에 import org.apache.commons.codec.*;할 수 있습니다import org.apache.commons.codec.binary.Hex;
cytinus

12
@ArtOfWarfare 나는 동의하지 않는다. 유일한 끔찍한 일은 아파치 공통 라이브러리가 기본적으로 JRE와 JDK에 포함되어 있지 않다는 것입니다. 기본적으로 클래스 경로에 있어야하는 유용한 라이브러리가 있습니다.이 라이브러리 중 하나입니다.
corsiKa

29
이 답변을 최고 답변으로 바꾸는 것이 좋습니다. 개선되지 않은 커스텀 코드를 통해 잘 테스트되고 성능이 뛰어난 오픈 소스 라이브러리를 사용하도록 항상 투표하십시오.
Dmitriy Likhten

6
또는 BouncyCastle ( org.bouncycastle : bcprov-jdk15on )을 사용하는 경우이 클래스를 다음 org.bouncycastle.util.encoders.Hex과 같이 사용할 수 있습니다 .String toHexString(byte[] data)
Guillaume Husta

320

JAXB (Java Architecture for XML Binding)javax.xml.bind.DatatypeConverter.printHexBinary() 의 일부인 이 메소드 는 a 를 16 진 문자열 로 변환하는 편리한 방법이었습니다 . 이 클래스에는 다른 유용한 데이터 조작 방법도 많이 포함되었습니다.byte[]DatatypeConverter

Java 8 및 이전 버전에서 JAXB는 Java 표준 라이브러리의 일부였습니다. 그것은 한 사용되지 않는 자바 9 및 제거 자바 (11)와 함께 자신의 라이브러리로 모든 Java EE 패키지를 이동하기위한 노력의 일환으로. 긴 이야기 입니다. 이제는 javax.xml.bind존재하지 않으며을 포함하는 JAXB를 사용 DatatypeConverter하려면 Maven에서 JAXB APIJAXB 런타임 을 설치해야합니다 .

사용법 예 :

byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);

결과는 다음과 같습니다.

000086003D

이 답변과 같은 이 하나 .


13
안타깝게도 Android에서 유효한 솔루션은 아니지만 좋은 솔루션입니다.
Kazriko

@Kazriko 아마도 code.google.com/p/dalvik/wiki/JavaxPackages 를 읽고 싶을 것 입니다. javax 클래스를 Android로 가져 오는 방법입니다. 그러나 16 진수로만 변환하려면 문제가되지 않습니다.
PhoneixS

13
DatatypeConverter가 더 이상 액세스 할 수 JDK 9 그대로
pmcollins하지

3
@PhoneixS 여전히 존재하지만 기본 런타임의 일부는 아닙니다 (Java 9 모듈로 인해).
스포트라이트

2
javax.xml.bind에 의존하지 않고 컴파일이 잘되지만 런타임에 찾을 수 없습니다. 그렇다면 java.lang.NoClassDefFoundError를 처리 할 준비를하십시오
Dmitry

227

가장 간단한 솔루션, 외부 라이브러리 없음, 숫자 상수 없음 :

public static String byteArrayToHex(byte[] a) {
   StringBuilder sb = new StringBuilder(a.length * 2);
   for(byte b: a)
      sb.append(String.format("%02x", b));
   return sb.toString();
}

14
이는 최고 응답의 평균보다 평균 1000 배 더 느린 (162 바이트 길이) 매우 느립니다. 성능이 중요한 경우 String.Format을 사용하지 마십시오.
pt123

8
아마 느려요. 로그인이나 이와 유사한 것과 같이 가끔 일어나는 일에 좋습니다.
포인터 Null

29
느리면 무엇? 내 유스 케이스에서는 디버그 명령문 만 사용 하므로이 코드 조각에 감사드립니다.
vikingsteve

8
수십 kB의 추가 JAR 파일을 포함하여 라이브러리를 재사용하면 필요한 모든 것이이 기능이면 정확하게 효율적이지 않습니다 (Android와 같은 일부 플랫폼에서는 전체 Jar가 최종 응용 프로그램에 포함됨). 때로는 성능이 필요하지 않을 때 더 짧고 명확한 코드가 더 좋습니다.
personne3000

2
@ personne3000, 그러나이 경우 단일 통화 기능이 아닌 스트림 지원이 필요합니다. 이것은 이해하고 기억하기 쉽기 때문에 유지하기가 쉽습니다.
Maarten Bodewes 2012 년

59

완전성을위한 구아바 솔루션 :

import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);

지금 hex"48656c6c6f20776f726c64"입니다.


구아바에서는를 사용할 수도 있습니다 new HashCode(bytes).toString().
mfulton26

1
Guava 22.0 기준HashCode.fromBytes(checksum).toString()
Devstr

43

이 간단한 oneliner는 나를 위해 일합니다.
String result = new BigInteger(1, inputBytes).toString(16);
편집-이것을 사용하면 선행 0이 제거되지만 내 유스 케이스에서 일했습니다. 지적 해 주셔서 감사합니다 @Voicu


56
oneliner는 선행 0 바이트를 삭제합니다.
Voicu

@Voicu ... 그리고 그것은 시간의 50 % 앞에 0을 추가합니다.
Maarten Bodewes

27

다음은 단순 (한 줄짜리)에서 복잡한 (거대한 라이브러리)에 이르는 일반적인 옵션입니다. 성능에 관심이 있다면 아래의 마이크로 벤치 마크를 참조하십시오.

옵션 1 : 코드 스 니펫-단순

매우 간단한 해결책 중 하나는 BigInteger의 16 진 표현 을 사용하는 것입니다 .

new BigInteger(1, someByteArray).toString(16)

참고이 손잡이 때문에 것을 없는 임의의 바이트 문자열 은 앞의 0을 생략합니다 -이 또는 당신이 (예를 들어 원하는 것을하지 않을 수 있습니다 000AE30AE33 바이트 입력). 이에 대해 매우 느린 또한 100 배 느린 다음 옵션에 비해.

옵션 2 : 코드 스 니펫-고급

대문자 / 소문자엔디안을 지원하는 모든 기능을 갖춘 복사 및 붙여 넣기 가능한 코드 스 니펫 입니다. 메모리 복잡성을 최소화하고 성능을 최대화하도록 최적화되었으며 모든 최신 Java 버전 (5+)과 호환되어야합니다.

private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};

public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {

    // our output size will be exactly 2x byte-array length
    final char[] buffer = new char[byteArray.length * 2];

    // choose lower or uppercase lookup table
    final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;

    int index;
    for (int i = 0; i < byteArray.length; i++) {
        // for little endian we count from last to first
        index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;

        // extract the upper 4 bit and look up char (0-A)
        buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
        // extract the lower 4 bit and look up char (0-A)
        buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
    }
    return new String(buffer);
}

public static String encode(byte[] byteArray) {
    return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}

Apache v2 라이센스 및 디코더가 포함 된 전체 소스 코드는 여기 에서 찾을 수 있습니다 .

옵션 3 : 작은 최적화 라이브러리 사용 : bytes-java

이전 프로젝트에서 작업하는 동안 Java에서 바이트로 작업하기위한이 작은 툴킷을 만들었습니다. 외부 종속성이 없으며 Java 7+와 호환됩니다. 여기에는 매우 빠르고 잘 테스트 된 HEX 인코더 / 디코더가 포함됩니다.

import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()

Github 에서 확인할 수 있습니다 : bytes-java .

옵션 4 : Apache Commons 코덱

물론 좋은 'ol commons 코덱 '이 있습니다. ( 앞서 경고 의견 ) 위에서 설명한 프로젝트를 진행하는 동안 나는 코드를 분석했고 매우 실망했다. 많은 중복 구성되지 않은 코드, 더 이상 사용되지 않는 이국적인 코덱은 널리 사용되는 코덱 (특히 Base64)의 구현이 매우 적고 느리게 구현 된 경우에만 유용합니다. 그러므로 나는 당신이 그것을 사용하거나 대안을 원한다면 정보에 근거한 결정을 내릴 것입니다. 어쨌든, 여전히 사용하려면 코드 스 니펫이 있습니다.

import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));

옵션 5 : 구글 구아바

더 자주 당신은 이미 구아바 를 의존으로 사용 하지 않습니다 . 그렇다면 다음을 사용하십시오.

import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);

옵션 6 : 스프링 보안

Spring Security 와 함께 Spring 프레임 워크 를 사용하는 경우 다음을 사용할 수 있습니다.

import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));

옵션 7 : 탄력성

보안 프레임 워크 Bouncy Castle 을 이미 사용중인 경우 해당 Hex유틸리티를 사용할 수 있습니다 .

import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);

실제로는 아님 옵션 8 : Java 9+ 호환성 또는 'JAXBs javax / xml / bind / DatatypeConverter를 사용하지 마십시오'

이전 Java (8 이하) 버전에서는 JAXB 용 Java 코드가 런타임 종속성으로 포함되었습니다. Java 9 및 Jigsaw는 모듈화 되기 때문에 코드가 명시 적 선언 없이는 모듈 외부의 다른 코드에 액세스 할 수 없습니다. 따라서 다음과 같은 예외가 발생하면주의하십시오.

java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

Java 9 이상이 설치된 JVM에서 실행할 때 그렇다면 구현을 위의 대안 중 하나로 전환하십시오. 이 질문 도 참조하십시오 .


마이크로 벤치 마크

다음은 크기가 다른 간단한 JMH 마이크로 벤치 마크 인코딩 바이트 배열의 결과입니다 . 값은 초당 작업이므로 높을수록 좋습니다. 마이크로 벤치 마크는 종종 실제 동작을 나타내지 않으므로 이러한 결과를 소금 한 알갱이로 가져 가십시오.

| Name (ops/s)         |    16 byte |    32 byte |  128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger     |  2,088,514 |  1,008,357 |   133,665 |       4 |
| Opt2/3: Bytes Lib    | 20,423,170 | 16,049,841 | 6,685,522 |     825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 |     529 |
| Opt5: Guava          | 10,177,925 |  6,937,833 | 2,094,658 |     257 |
| Opt6: Spring         | 18,704,986 | 13,643,374 | 4,904,805 |     601 |
| Opt7: BC             |  7,501,666 |  3,674,422 | 1,077,236 |     152 |
| Opt8: JAX-B          | 13,497,736 |  8,312,834 | 2,590,940 |     346 |

사양 : JDK 8u202, i7-7700K, Win10, 24GB Ram. 여기 에서 전체 벤치 마크를 참조 하십시오 .



21

해시와 같이 고정 길이에 다음과 같은 것을 사용합니다.

md5sum = String.format("%032x", new BigInteger(1, md.digest()));

2
고마워요, 이건 너무나 화려하고 적절합니다.
Deepan Prabhu Babu

17

나는 여기에서 세 가지 다른 방법을 발견했다 : http://www.rgagnon.com/javadetails/java-0596.html

그가 언급했듯이 가장 우아한 것은 이것입니다.

static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
    if ( raw == null ) {
        return null;
    }
    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();
}

다른 방법은 5ms에서 64 바이트 샘플에서 실행 중이며 0ms에서 실행됩니다. 아마도 형식과 같은 다른 문자열 함수가 없을 때 가장 좋습니다.
Joseph Lust

if (raw == null) return null빨리 실패하지 않습니다. 왜 null열쇠를 사용 하겠습니까?
Maarten Bodewes

유효성 검사를 입력하는 습관이 있다고 가정합니다. 이 경우 Null 참조 예외를 방지하고 잘못된 데이터를 처리하기 위해 호출자에게 맡깁니다.
Michael Bisbjerg

16

룩업 테이블을 저장하는 데 드는 적은 비용으로이 구현은 간단하고 매우 빠릅니다.

 private static final char[] BYTE2HEX=(
    "000102030405060708090A0B0C0D0E0F"+
    "101112131415161718191A1B1C1D1E1F"+
    "202122232425262728292A2B2C2D2E2F"+
    "303132333435363738393A3B3C3D3E3F"+
    "404142434445464748494A4B4C4D4E4F"+
    "505152535455565758595A5B5C5D5E5F"+
    "606162636465666768696A6B6C6D6E6F"+
    "707172737475767778797A7B7C7D7E7F"+
    "808182838485868788898A8B8C8D8E8F"+
    "909192939495969798999A9B9C9D9E9F"+
    "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+
    "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+
    "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
    "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+
    "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+
    "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray();
   ; 

  public static String getHexString(byte[] bytes) {
    final int len=bytes.length;
    final char[] chars=new char[len<<1];
    int hexIndex;
    int idx=0;
    int ofs=0;
    while (ofs<len) {
      hexIndex=(bytes[ofs++] & 0xFF)<<1;
      chars[idx++]=BYTE2HEX[hexIndex++];
      chars[idx++]=BYTE2HEX[hexIndex];
    }
    return new String(chars);
  }

6
BYTE2HEX간단한 for주기로 어레이를 초기화하지 않겠습니까?
icza

@icza 정적 최종 (일명 상수) 필드에서도 가능합니까?
nevelis

1
@nevelis static { }블록 으로 할당 될 수 있습니다 .
マ ル ち ゃ ん だ よ

1
조회 테이블을 생성하는 것보다 하드 코딩하는 것이 더 빠르기 때문에 @icza. 여기서 메모리 복잡성은 시간 복잡성과 교환된다. (모든 양쪽 끝에서 약간) 더 많은 메모리를 필요로하지만, 빠른
패트릭 파브르

8

이건 어때요?

    String byteToHex(final byte[] hash)
    {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

3

외부 라이브러리를 사용하거나 루프와 상수를 기반으로 코드를 작성할 필요가 없습니다.
이것으로 충분합니다.

byte[] theValue = .....
String hexaString = new BigInteger(1, theValue).toString(16);

1
이것은 everconfusedGuy의 답변과 매우 유사합니다.
Scratte

2

나는 이것을 사용하는 것을 선호한다 :

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes, int offset, int count) {
    char[] hexChars = new char[count * 2];
    for ( int j = 0; j < count; j++ ) {
        int v = bytes[j+offset] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

허용되는 답변을 약간 더 융통성있게 적용합니다. 개인적으로, 나는 받아 들여진 대답 과이 과부하를 더 많은 맥락에서 사용할 수 있도록 유지합니다.


원래 질문은 byte [] to String입니다. 16 진수를 바이트 []로 보거나 다른 질문 @NonExistent를 요청하십시오.
Bamaco

2

나는 보통 debuf 문에 다음과 같은 방법을 사용하지만 그것이 최선의 방법인지 아닌지는 모르겠습니다.

private static String digits = "0123456789abcdef";

public static String toHex(byte[] data){
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i != data.length; i++)
    {
        int v = data[i] & 0xff;
        buf.append(digits.charAt(v >> 4));
        buf.append(digits.charAt(v & 0xf));
    }
    return buf.toString();
}

2
디 버퍼에 나쁜 하루가 있다면 StringBuilder 인스턴스화에서 여러 문자를 사용하여 다음을 지원하십시오 StringBuilder buf = new StringBuilder(data.length * 2);.
greybeard

2

좋습니다.이 작업을 수행하는 많은 방법이 있지만 라이브러리를 사용하기로 결정한 경우 새 라이브러리를 추가하기 전에 이미 프로젝트의 일부인 라이브러리에 무언가가 구현되어 있는지 확인하기 위해 프로젝트에서 파킹하는 것이 좋습니다. 그냥 이렇게 예를 들어 아직없는 경우

org.apache.commons.codec.binary.Hex

아마도 당신은 ...

org.apache.xerces.impl.dv.util.HexBin


2

Spring Security 프레임 워크를 사용하는 경우 다음을 사용할 수 있습니다.

import org.springframework.security.crypto.codec.Hex

final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));

2

간단한 기능을 위해 유틸리티 병을 추가하는 것은 좋은 옵션이 아닙니다. 대신 자신의 유틸리티 클래스를 조립하십시오. 다음은 더 빠른 구현이 가능합니다.

public class ByteHex {

    public static int hexToByte(char ch) {
        if ('0' <= ch && ch <= '9') return ch - '0';
        if ('A' <= ch && ch <= 'F') return ch - 'A' + 10;
        if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
        return -1;
    }

    private static final String[] byteToHexTable = 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"
    };

    private static final String[] byteToHexTableLowerCase = 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 byteToHexTable[b & 0xFF];
    }

    public static String byteToHex(byte[] bytes){
        if(bytes == null) return null;
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
        return sb.toString();
    }

    public static String byteToHex(short[] bytes){
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
        return sb.toString();
    }

    public static String byteToHexLowerCase(byte[] bytes){
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
        return sb.toString();
    }

    public static byte[] hexToByte(String hexString) {
        if(hexString == null) return null;
        byte[] byteArray = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
        }
        return byteArray;
    }

    public static byte hexPairToByte(char ch1, char ch2) {
        return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
    }


}

1

@maybewecouldstealavan이 제안한 솔루션의 작은 변형으로, 출력 16 진 문자열에 N 바이트를 시각적으로 묶을 수 있습니다.

 final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
 final static char BUNDLE_SEP = ' ';

public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) {
        char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)];
        for (int j = 0, k = 1; j < bytes.length; j++, k++) {
                int v = bytes[j] & 0xFF;
                int start = (j * 2) + j/bundleSize;

                hexChars[start] = HEX_ARRAY[v >>> 4];
                hexChars[start + 1] = HEX_ARRAY[v & 0x0F];

                if ((k % bundleSize) == 0) {
                        hexChars[start + 2] = BUNDLE_SEP;
                }   
        }   
        return new String(hexChars).trim();    
}

그건:

bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E

bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E

1

이 페이지에서 해결되지 않은 솔루션을 찾을 수 없습니다

  1. 루프를 사용하십시오
  2. 컴파일은되지만 런타임에 java.lang.NoClassDefFoundError가 발생하는 javax.xml.bind.DatatypeConverter를 사용하십시오.

여기에 결함이없는 해결책이 있습니다 (그러나 다른 결함이 없다고 약속하지는 않습니다)

import java.math.BigInteger;

import static java.lang.System.out;
public final class App2 {
    // | proposed solution.
    public static String encode(byte[] bytes) {          
        final int length = bytes.length;

        // | BigInteger constructor throws if it is given an empty array.
        if (length == 0) {
            return "00";
        }

        final int evenLength = (int)(2 * Math.ceil(length / 2.0));
        final String format = "%0" + evenLength + "x";         
        final String result = String.format (format, new BigInteger(bytes));

        return result;
    }

    public static void main(String[] args) throws Exception {
        // 00
        out.println(encode(new byte[] {})); 

        // 01
        out.println(encode(new byte[] {1})); 

        //203040
        out.println(encode(new byte[] {0x20, 0x30, 0x40})); 

        // 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e
        out.println(encode("All your base are belong to us.".getBytes()));
    }
}   

62 opcodes에서이를 얻을 수는 없지만 첫 번째 바이트가 0x10보다 작은 경우 0 패딩없이 살 수 있다면 다음 솔루션은 23 opcode 만 사용합니다. 네이티브 구현이 아직 사용 가능하지 않은 경우 (또는이 경우 BigInteger에 0으로 접두어 붙일 수있는 옵션이있는 경우 "문자열 길이가 홀수 인 경우 패드가 0 인 패드"와 같은 "직접 구현하기 쉬운"솔루션이 비용이 많이 드는 방법을 실제로 보여줍니다. toString).

public static String encode(byte[] bytes) {          
    final int length = bytes.length;

    // | BigInteger constructor throws if it is given an empty array.
    if (length == 0) {
        return "00";
    }

    return new BigInteger(bytes).toString(16);
}

1

내 솔루션은 maybeWeCouldStealAVan의 솔루션을 기반으로하지만 추가로 할당 된 조회 테이블에 의존하지 않습니다. 'int-to-char'캐스트 해킹을 사용하지 않습니다 (실제로 Character.forDigit()숫자를 실제로 비교하기 위해 비교를 수행합니다). 따라서 조금 느려질 수 있습니다. 원하는 곳 어디에서나 자유롭게 사용하십시오. 건배.

public static String bytesToHex(final byte[] bytes)
{
    final int numBytes = bytes.length;
    final char[] container = new char[numBytes * 2];

    for (int i = 0; i < numBytes; i++)
    {
        final int b = bytes[i] & 0xFF;

        container[i * 2] = Character.forDigit(b >>> 4, 0x10);
        container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10);
    }

    return new String(container);
}

0

// 바이트 이동이 더 효율적입니다. // 이것도 사용할 수 있습니다

public static String getHexString (String s) 
{
    byte[] buf = s.getBytes();

    StringBuffer sb = new StringBuffer();

    for (byte b:buf)
    {
        sb.append(String.format("%x", b));
    }


        return sb.toString();
}

0

파이썬과 정확히 같은 바이트 배열을 찾고 있다면이 Java 구현을 파이썬으로 변환했습니다.

class ByteArray:

@classmethod
def char(cls, args=[]):
    cls.hexArray = "0123456789ABCDEF".encode('utf-16')
    j = 0
    length = (cls.hexArray)

    if j < length:
        v = j & 0xFF
        hexChars = [None, None]
        hexChars[j * 2] = str( cls.hexArray) + str(v)
        hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F)
        # Use if you want...
        #hexChars.pop()

    return str(hexChars)

array = ByteArray()
print array.char(args=[])

0
  public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
        + Character.digit(s.charAt(i+1), 16));
    }
  return data;
  } 

0

다음은 java.util.Base64비슷한 구현 (부분)입니다. 예쁘지 않습니까?

public class Base16/*a.k.a. Hex*/ {
    public static class Encoder{
        private static char[] toLowerHex={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        private static char[] toUpperHex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        private boolean upper;
        public Encoder(boolean upper) {
            this.upper=upper;
        }
        public String encode(byte[] data){
            char[] value=new char[data.length*2];
            char[] toHex=upper?toUpperHex:toLowerHex;
            for(int i=0,j=0;i<data.length;i++){
                int octet=data[i]&0xFF;
                value[j++]=toHex[octet>>4];
                value[j++]=toHex[octet&0xF];
            }
            return new String(value);
        }
        static final Encoder LOWER=new Encoder(false);
        static final Encoder UPPER=new Encoder(true);
    }
    public static Encoder getEncoder(){
        return Encoder.LOWER;
    }
    public static Encoder getUpperEncoder(){
        return Encoder.UPPER;
    }
    //...
}

0
private static String bytesToHexString(byte[] bytes, int length) {
        if (bytes == null || length == 0) return null;

        StringBuilder ret = new StringBuilder(2*length);

        for (int i = 0 ; i < length ; i++) {
            int b;

            b = 0x0f & (bytes[i] >> 4);
            ret.append("0123456789abcdef".charAt(b));

            b = 0x0f & bytes[i];
            ret.append("0123456789abcdef".charAt(b));
        }

        return ret.toString();
    }

0
Converts bytes data to hex characters

@param bytes byte array to be converted to hex string
@return byte String in hex format

private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.