누군가 바이트 배열에서 16 진수로 변환을 설명 할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/1043276

  •  20-08-2019
  •  | 
  •  

문제

나는 최근에 MD5 Hashing (Java)을보기 시작했고 그것을 달성하는 데 도움이되는 알고리즘과 방법을 찾았지만 실제로 어떻게 작동하는지 궁금해하고 있습니다.

우선, 나는 다음을 발견했다 이 URL:

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();
}

나는 Java에서 비트 시프트를 사용할 필요가 없어서 약간 녹슬 었습니다. (간단한 용어로) 위의 코드는 어떻게 전환을 하는가? ">>>"?

또한 STACKOVERFLOW에서 다른 솔루션을 찾았습니다. 여기 그리고 여기, 대신 biginteger를 사용하는 것 :

try {
   String s = "TEST STRING";
   MessageDigest md5 = MessageDigest.getInstance("MD5");
   md5.update(s.getBytes(),0,s.length());
   String signature = new BigInteger(1,md5.digest()).toString(16);
   System.out.println("Signature: "+signature);

} catch (final NoSuchAlgorithmException e) {
   e.printStackTrace();
}

왜 그것이 효과가 있고 어떤 방법이 더 효율적입니까?

시간 내 줘서 고마워.

도움이 되었습니까?

해결책

private static String convertToHex(byte[] data) {
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; i++) {

이 시점까지 ... 기본 설정과 배열의 모든 바이트를 통과하기 위해 루프를 시작합니다.

        int halfbyte = (data[i] >>> 4) & 0x0F;

바이트는 16 진수로 변환 될 때의 바이트는 당신이 그것을 보는베이스에 따라 2 개의 16 진수 숫자 또는 8 바이너리 숫자입니다. 위의 진술은 높은 4 비트를 아래로 아래로 이동시키고 (>>> 서명되지 않은 오른쪽 시프트) 논리적으로 0000 1111로 이동합니다. 결과는 바이트의 높은 4 비트 (첫 번째 16 진수)와 동일한 정수입니다.

23은 입력이고 이진에서 0001 0111입니다. 교대는 논리적이며 이것을 0000 0001로 커버합니다.

        int two_halfs = 0;
        do {

이것은 단지 do/while 루프를 두 번 실행하도록 설정합니다.

            if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));

여기에 우리는 기본적으로 0 또는 캐릭터를 시작점으로 사용하고 올바른 문자로 이동하는 실제 16 진수 자리를 표시합니다. 첫 번째 IF 문은 모든 숫자 0-9를 다루고 두 번째는 모든 숫자 10-15 (AF in Hex)를 다룹니다.

다시 한 번, 소수점에서 0000 0001을 사용하는 것은 1과 같다. 우리는 상단 if 블록에 잡히고 '0'문자에 1을 추가하여 문자 '1'을 얻고 문자열에 그것을 추가하고 계속 움직입니다.

                halfbyte = data[i] & 0x0F;

이제 우리는 정수를 바이트와 반복의 낮은 비트와 동일하게 설정했습니다.

다시 말하지만, 우리의 입력이 논리 후 23 ... 0001 0111이면 0000 0111이면 소수점에서 7입니다. 위와 동일한 논리를 반복하면 문자 '7'이 표시됩니다.

            } while(two_halfs++ < 1);

이제 우리는 배열의 다음 바이트로 이동하고 반복합니다.

        }
    return buf.toString();
}

다음 질문에 답하기 위해 Java API에는 이미 BigInteger에 이미 내장 된 기본 변환 유틸리티가 있습니다. 참조 Tostring (int radix) 선적 서류 비치.

Java API가 사용한 구현을 알지 못하면 확실히 말할 수는 없지만 Java Implenentation이 게시 한 첫 번째 다소 간단한 알고리즘보다 더 효율적이라고 생각합니다.

다른 팁

이 비트에 답하기 위해 :

왜 그게 작동합니까?

그렇지 않습니다. 최소한 루프 버전과 같은 방식이 아닙니다. New Biginteger (...). Tostring (16)은 이전 버전이 할 주요 0을 보여주지 않을 것입니다. 일반적으로 바이트 배열 (특히 해시와 같은 것을 나타내는 배열)을 쓰는 것과 같은 경우 고정 길이 출력을 원할 것이므로 해당 버전을 사용하려면 적절하게 패드해야합니다.

Bitshifting에 대한 철저한 설명은 다음 질문에서 답을 확인하십시오.비트 시프트 (비트 시프트) 운영자는 무엇이며 어떻게 작동합니까?

그는 하나의 단일 바이트를 16보다 작은 숫자로 변환하려고 시도하는 것 같습니다. 따라서 바이트가 코드를 나타내는 Caracther를 쉽게 결정할 수 있습니다.

  if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));

이것은 단순한 대답이지만, 어쨌든 그렇게 밝지는 않습니다 = D

이 물건은 이미 Apache-Commons-Codec로 작성 되었기 때문에 스스로 쓸 필요가 없습니다.

import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(byte[] array)

더 유용한 방법이 많이 있습니다 Hex 수업.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top