Java를 사용하여 16 진 덤프의 문자열 표시를 바이트 배열로 변환 하시겠습니까?


372

16 진수 값을 바이트 배열로 나타내는 긴 문자열 (덤프에서)을 변환하는 방법을 찾고 있습니다.

나는 같은 질문을 여기에 올린 사람보다 더 잘 표현할 수 없었 습니다 .

그러나 그것을 독창적으로 유지하기 위해, 나는 그것을 내 자신의 방식으로 표현할 "00A0BF"것입니다.

byte[] {0x00,0xA0,0xBf}

어떻게해야합니까?

나는 Java 초보자이며 BigInteger16 진수 0을 사용 하고 감시했습니다. 그러나 나는 그것이 추악하다고 생각하고 간단한 것을 놓치고 있다고 확신합니다.



나는 BigInteger 여기 길들여 졌다 .
John McClane

FWIW String.getBytes()는 생각 한대로 작동하지 않습니다. 이것을 어려운 방법으로 배웠습니다. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
tir38

답변:


636

여기에 지금까지 게시 된 것보다 낫다고 생각하는 솔루션이 있습니다.

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 (BigInteger와 달리)과 음의 바이트 값 (Byte.parseByte와는 다름)으로 안전합니다.

  • String을로 변환하지 않거나 char[]모든 단일 바이트에 대해 StringBuilder 및 String 객체를 만듭니다.

  • 사용 불가능한 라이브러리 종속성이 없습니다.

assert인수가 안전한 것으로 알려진 경우 인수 검사를 통해 또는 예외 를 추가하십시오 .


2
잘못 디코딩 된 예를 제시하거나 어떻게 잘못되었는지 설명 할 수 있습니까?
Dave L.

5
문자열 "0"에는 작동하지 않습니다. java.lang.StringIndexOutOfBoundsException
ovdsrn

49
"0"은 유효한 입력이 아닙니다. 바이트는 각각 2 개의 16 진수를 요구합니다. 답변에 따르면, "인수 검사를 추가 할 필요가 없습니다 ... 인수가 안전하지 않다면"
Dave L.

12
javax.xml.bind.DatatypeConverter.parseHexBinary (hexString)은 마이크로 테스트에서 위의 솔루션보다 가치가 약 20 % 빠르며 (입력 할 가치가있는 것이 무엇이든) 잘못된 입력 (예 : "gg" 유효한 hexString은 아니지만 제안 된 솔루션을 사용하여 -77을 반환합니다).
트레버 프리먼

6
@ DaedalusAlpha 상황에 따라 다르지만 일반적으로 잘못된 데이터를 자동으로 반환하는 대신 가정을 해결할 수 있도록 그러한 문제로 빠르게 실패하는 것이 좋습니다.
Dave L.

331

원 라이너 :

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

경고 :

  • Java 9 Jigsaw에서 이것은 더 이상 (기본) java.se 루트 세트의 일부가 아니므로 --add-modules java.se.ee를 지정하지 않으면 ClassNotFoundException이 발생합니다 (@ 덕분에 eckes)
  • 안드로이드에서는 사용할 수 Fabian없지만 (그렇기 때문에) 시스템 에 어떤 이유로 부족한 경우 소스 코드를 가져올 수 있습니다 javax.xml. Bert Regelink소스를 추출한 @ 에게 감사합니다 .

14
IMHO 이것은 @DaveL의 답변과 달리 짧고 깨끗 하며 skaffman의 답변과 같은 외부 라이브러리가 필요하지 않기 때문에 허용 / 최고 답변이어야합니다 . 또한 <자전거 재창조에 관한 낡은 농담을 입력하십시오> .
Priidu Neemre

9
예를 들어 datatypeconverter 클래스는 안드로이드에서 사용할 수 없습니다.
Fabian

4
경고 : Java 9 Jigsaw에서는 더 이상 (기본) java.se루트 세트 의 일부가 ClassNotFoundException--add-modules java.se.ee
아니므로

2
@dantebarba javax.xml.bind.DatatypeConverter이미 Base64 데이터를 인코딩 / 디코딩하는 방법을 제공 한다고 생각 합니다. 참조 parseBase64Binary()printBase64Binary().
DragShot

2
의 문제에 추가하기 위해 DataTypeConverterJava SE 11은 JAXB API를 완전히 제거했으며 이제는 Java EE에만 포함됩니다. 여기에 제안 된대로 Maven 종속성으로 추가 할 수도 있습니다. stackoverflow.com/a/43574427/7347751
David Mordigal

79

commons-codec의 Hex 클래스가 그렇게해야합니다.

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF

6
이것도 좋아 보인다. org.apache.commons.codec.binary.Hex.decodeHex () 참조
Dave L.

그것은 흥미로웠다. 그러나 나는 그들의 해결책을 따르기가 어렵다는 것을 알았습니다. 짝수의 문자를 확인하는 것 외에 제안한 것보다 이점이 있습니까?
rafraf

38

이제 BaseEncoding 을 사용 guava하여이를 수행 할 수 있습니다 .

BaseEncoding.base16().decode(string);

그것을 반대로 사용하려면

BaseEncoding.base16().encode(bytes);

27

실제로 BigInteger가 솔루션이라고 생각합니다.

new BigInteger("00A0BF", 16).toByteArray();

편집 : 포스터에서 언급했듯이 선행 0에 안전하지 않습니다 .


나는 또한 처음에 그렇게 생각했다. 그리고 문서화 해 주셔서 감사합니다-방금 생각해야했습니다 ... 실제로 이해하지 못했지만 이상한 일을했습니다. 일부 0x00을 생략하고 156 바이트 문자열에서 1 바이트의 순서를 섞는 것처럼 놀고 있었다.
rafraf

2
그것은 0을 이끄는 것에 대한 좋은 지적입니다. 바이트 순서를 섞을 수 있다고 확신하지 못하며 시연을 보는 데 매우 관심이 있습니다.
Dave L.

1
그래, 내가 말하자마자 나도 믿지 않았다 :) BigInteger의 바이트 배열과 mmyers'fromHexString을 비교하고 (0x00이 없음) 문제가되는 문자열에 대해 비교했습니다. "혼합"이 발생했지만 다른 것일 수 있습니다. 나는 내일 더 자세히 볼 것이다
rafraf

3
BigInteger의 문제점은 "부호 비트"가 있어야한다는 것입니다. 선행 바이트에 높은 비트 세트가 있으면 결과 바이트 배열의 첫 번째 위치에 추가 0이 있습니다. 그러나 여전히 +1입니다.
그레이

25

원 라이너 :

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

뒤에서 실제 코드에 관심이있는 당신의 그것들을 위해 한 - 라이너 에서 FractalizeR 이 출처 (나는 javax.xml.bind의 기본적으로 안드로이드 ()를 사용할 수 없습니다 때문에 것을 필요) com.sun.xml.internal.bind. DatatypeConverterImpl.java :

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if( len%2 != 0 )
        throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);

    byte[] out = new byte[len/2];

    for( int i=0; i<len; i+=2 ) {
        int h = hexToBin(s.charAt(i  ));
        int l = hexToBin(s.charAt(i+1));
        if( h==-1 || l==-1 )
            throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);

        out[i/2] = (byte)(h*16+l);
    }

    return out;
}

private static int hexToBin( 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 char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length*2);
    for ( byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}

3
기본적으로 Java 9에서는 DatatypeConverter를 사용할 수 없습니다. 위험한 것은 Java 1.8 이전 버전 (소스 설정이 이전 인 Java 9)에서 컴파일되지만 "--add-modules java.se.ee"가없는 Java 9에서는 런타임 예외가 발생하는 코드입니다.
Stephen M-on strike-

24

HexBinaryAdapter정렬 화하는 능력 사이의 비 정렬 화 제공 String등을 byte[].

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public byte[] hexToBytes(String hexString) {
     HexBinaryAdapter adapter = new HexBinaryAdapter();
     byte[] bytes = adapter.unmarshal(hexString);
     return bytes;
}

그것은 내가 입력 한 예제 일뿐입니다 ... 실제로 그대로 사용하므로 별도의 방법을 사용할 필요가 없습니다.


5
입력 문자열 (hexString)에 짝수의 문자가있는 경우에만 작동합니다. 그렇지 않은 경우 : "main"스레드의 예외 java.lang.IllegalArgumentException : hexBinary의 길이는 짝수
여야합니다

3
아, 지적 해줘서 고마워 바이트 배열이 {0x00,0xA0,0xBf}로 표시되므로 사용자는 실제로 홀수의 문자를 가져서는 안됩니다. 각 바이트에는 2 개의 16 진수 또는 니블이 있습니다. 따라서 임의의 수의 바이트에는 항상 짝수의 문자가 있어야합니다. 언급 해 주셔서 감사합니다.
GrkEngineer 2016 년

8
HexBinaryAdapter (DatatypeConverter를 호출 함)를 사용하는 대신 java.xml.bind.DatatypeConverter.parseHexBinary (hexString)를 직접 사용할 수 있습니다. 이런 식으로 DatatypeConverter 메소드가 정적이므로 어댑터 인스턴스 오브젝트를 작성할 필요가 없습니다.
Trevor Freeman

javax.xml.bind. *는 더 이상 Java 9에서 사용할 수 없습니다. 위험한 것은 Java 1.8 이전 버전 (소스 설정이 이전 인 Java 9)에서 컴파일되지만 Java 9에서 실행되는 런타임 예외를 사용하는 코드입니다.
Stephen M-on strike-

15

실제로 작동하는 방법은 다음과 같습니다 (몇 가지 이전 반 정답에 기반).

private static byte[] fromHexString(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

내가 볼 수있는 유일한 문제는 입력 문자열이 매우 긴 경우입니다. toCharArray ()를 호출하면 문자열의 내부 배열이 복사됩니다.

편집 : 아, 그리고 바이트는 Java로 서명되므로 입력 문자열은 [0, 160, 191] 대신 [0, -96, -65]로 변환됩니다. 그러나 당신은 아마 그것을 이미 알고있을 것입니다.


1
고마워 마이클-당신은 생명의 은인입니다! RIM의 "Byte.parseByte (byteString, 16)"메소드를 사용하여 BlackBerry 프로젝트에서 작업하고 바이트의 문자열 표현을 다시 바이트로 변환하려고합니다. NumberFormatExcpetion을 던졌습니다. 이유를 알아 내기 위해 시간을 보냈다. "Integer.praseInt ()"에 대한 귀하의 제안이 트릭을 만들었습니다. 다시 감사합니다 !!
BonanzaDriver

12

안드로이드에서 16 진수로 작업하는 경우 okio 를 시도 할 수 있습니다 .

간단한 사용법 :

byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();

결과는

[-64, 0, 6, 0, 0]

나는 많은 다른 방법을 테스트했지만이 방법은 적어도 두 배 빠릅니다!
poby

5

BigInteger()java.math 의 메소드는 매우 느리고 명령을 지정할 수 없습니다.

Integer.parseInt(HEXString, 16)

Digit / Integer로 변환하지 않고 일부 문자에 문제가 발생할 수 있습니다

잘 작동하는 방법 :

Integer.decode("0xXX") .byteValue()

함수:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

재미 있고 행운을 빕니다


4

편집 : @mmyers가 지적한 것처럼이 방법은 높은 비트 세트 ( "80"- "FF")의 바이트에 해당하는 하위 문자열이 포함 된 입력에서는 작동하지 않습니다. 설명은 버그 ID : 6259307 Byte.parseByte가 SDK 설명서에 알려진대로 작동하지 않습니다 .

public static final byte[] fromHexString(final String s) {
    byte[] arr = new byte[s.length()/2];
    for ( int start = 0; start < s.length(); start += 2 )
    {
        String thisByte = s.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    return arr;
}

1
닫기, 그러나 주어진 입력 "00A0BBF"에서이 방법이 실패합니다. bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307을 참조하십시오 .
마이클 마이어스

1
또한 이상하게도 "9C"를 다루지 않습니다
rafraf

1
@mmyers : 우와. 그 좋지 않다. 혼란을 드려 죄송합니다. @ravigad : 9C는이 경우 높은 비트가 설정되므로 같은 문제가 있습니다.
블레어 콘래드

(byte) Short.parseShort (thisByte, 16)는이 문제를 해결합니다
Jamey Hicks

3

가치있는 것을 위해, 여기에 문자열 연결에 의존하지 않고 홀수 길이 문자열을 지원하는 다른 버전이 있습니다.

public static byte[] hexStringToByteArray(String input) {
    int len = input.length();

    if (len == 0) {
        return new byte[] {};
    }

    byte[] data;
    int startIdx;
    if (len % 2 != 0) {
        data = new byte[(len / 2) + 1];
        data[0] = (byte) Character.digit(input.charAt(0), 16);
        startIdx = 1;
    } else {
        data = new byte[len / 2];
        startIdx = 0;
    }

    for (int i = startIdx; i < len; i += 2) {
        data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
                + Character.digit(input.charAt(i+1), 16));
    }
    return data;
}

2

나는 항상 같은 방법을 사용했다

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

이 방법은 공백으로 구분 된 16 진수 값으로 분할되지만 문자열을 두 문자 그룹화와 같은 다른 기준으로 분할하는 것은 어렵지 않습니다.


문자열 연결이 필요하지 않습니다. Integer.valueOf (val, 16)를 사용하십시오.
마이클 마이어스

나는 전에 같은 기수 변환을 사용하여 시도하고 나는 혼합 된 결과를 했어
pfranza

감사합니다-이상하게도 "9C001C"또는 "001C21"문자열에서 제대로 작동하고 다음과 같이 실패합니다. "9C001C21" "main"스레드 예외 java.lang.NumberFormatException : 입력 문자열 : java.lang의 "9C001C21"
forInputString

( Byte/의 byte경우 보다 더 이상하지 않습니다 : 선행없는 비트 세트-)
greybeard

2

Character.digit 솔루션을 좋아하지만 여기에 해결 방법이 있습니다.

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}

2

Bert Regelink가 제시 한 규범은 단순히 작동하지 않습니다. 다음을 시도하십시오 :

import javax.xml.bind.DatatypeConverter;
import java.io.*;

public class Test
{  
    @Test
    public void testObjectStreams( ) throws IOException, ClassNotFoundException
    {     
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);

            String stringTest = "TEST";
            oos.writeObject( stringTest );

            oos.close();
            baos.close();

            byte[] bytes = baos.toByteArray();
            String hexString = DatatypeConverter.printHexBinary( bytes);
            byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);

            assertArrayEquals( bytes, reconvertedBytes );

            ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
            ObjectInputStream ois = new ObjectInputStream(bais);

            String readString = (String) ois.readObject();

            assertEquals( stringTest, readString);
        }
    }

2
이것은 실제로 다른 문제이며 다른 스레드에 속할 수 있습니다.
Sean Coffey

1

커널 패닉이 가장 유용한 솔루션을 찾았지만 16 진수 문자열이 홀수이면 문제가 발생했습니다. 이 방법으로 해결했습니다.

boolean isOdd(int value)
{
    return (value & 0x01) !=0;
}

private int hexToByte(byte[] out, int value)
{
    String hexVal = "0123456789ABCDEF"; 
    String hexValL = "0123456789abcdef";
    String st = Integer.toHexString(value);
    int len = st.length();
    if (isOdd(len))
        {
        len+=1; // need length to be an even number.
        st = ("0" + st);  // make it an even number of chars
        }
    out[0]=(byte)(len/2);
    for (int i =0;i<len;i+=2)
    {
        int hh = hexVal.indexOf(st.charAt(i));
            if (hh == -1)  hh = hexValL.indexOf(st.charAt(i));
        int lh = hexVal.indexOf(st.charAt(i+1));
            if (lh == -1)  lh = hexValL.indexOf(st.charAt(i+1));
        out[(i/2)+1] = (byte)((hh << 4)|lh);
    }
    return (len/2)+1;
}

배열에 여러 16 진수를 추가하고 있으므로 사용중인 배열에 대한 참조를 전달하고 int 변환하고 다음 16 진수의 상대 위치를 반환해야합니다. 따라서 최종 바이트 배열에는 [0] 개의 16 진 쌍, [1 ...] 개의 16 진 쌍, 그 다음에 쌍의 수가 있습니다 ...


1

반대 투표 솔루션에 따라 다음이 조금 더 효율적이어야합니다.

  public static byte [] hexStringToByteArray (final String s) {
    if (s == null || (s.length () % 2) == 1)
      throw new IllegalArgumentException ();
    final char [] chars = s.toCharArray ();
    final int len = chars.length;
    final byte [] data = new byte [len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
    }
    return data;
  }

char 배열로의 초기 변환은 charAt에서 길이 검사를 아끼지 않습니다.


1

코딩 스타일로 Java 8 스트림을 선호하는 경우 JDK 프리미티브 만 사용하면됩니다.

String hex = "0001027f80fdfeff";

byte[] converted = IntStream.range(0, hex.length() / 2)
    .map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
    .collect(ByteArrayOutputStream::new,
             ByteArrayOutputStream::write,
             (s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
    .toByteArray();

, 0, s2.size()catch를 신경 쓰지 않으면 수집기 연결 기능 의 매개 변수를 생략 할 수 있습니다 IOException.


0
public static byte[] hex2ba(String sHex) throws Hex2baException {
    if (1==sHex.length()%2) {
        throw(new Hex2baException("Hex string need even number of chars"));
    }

    byte[] ba = new byte[sHex.length()/2];
    for (int i=0;i<sHex.length()/2;i++) {
        ba[i] = (Integer.decode(
                "0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
    }
    return ba;
}

0

내 공식 솔루션 :

/**
 * Decodes a hexadecimally encoded binary string.
 * <p>
 * Note that this function does <em>NOT</em> convert a hexadecimal number to a
 * binary number.
 *
 * @param hex Hexadecimal representation of data.
 * @return The byte[] representation of the given data.
 * @throws NumberFormatException If the hexadecimal input string is of odd
 * length or invalid hexadecimal string.
 */
public static byte[] hex2bin(String hex) throws NumberFormatException {
    if (hex.length() % 2 > 0) {
        throw new NumberFormatException("Hexadecimal input string must have an even length.");
    }
    byte[] r = new byte[hex.length() / 2];
    for (int i = hex.length(); i > 0;) {
        r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
    }
    return r;
}

private static int digit(char ch) {
    int r = Character.digit(ch, 16);
    if (r < 0) {
        throw new NumberFormatException("Invalid hexadecimal string: " + ch);
    }
    return r;
}

등이다 PHP의 HEX2BIN () 함수 하지만 자바 스타일.

예:

String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"

0

파티에 늦었지만 나는 도움이 될 경우를 대비하여 DaveL의 위의 답변을 반대 행동으로 수업에 합병했습니다.

public final class HexString {
    private static final char[] digits = "0123456789ABCDEF".toCharArray();

    private HexString() {}

    public static final String fromBytes(final byte[] bytes) {
        final StringBuilder buf = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
            buf.append(HexString.digits[bytes[i] & 0x0f]);
        }
        return buf.toString();
    }

    public static final byte[] toByteArray(final String hexString) {
        if ((hexString.length() % 2) != 0) {
            throw new IllegalArgumentException("Input string must contain an even number of characters");
        }
        final int len = hexString.length();
        final byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}

그리고 JUnit 테스트 클래스 :

public class TestHexString {

    @Test
    public void test() {
        String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};

        for (int i = 0; i < tests.length; i++) {
            String in = tests[i];
            byte[] bytes = HexString.toByteArray(in);
            String out = HexString.fromBytes(bytes);
            System.out.println(in); //DEBUG
            System.out.println(out); //DEBUG
            Assert.assertEquals(in, out);

        }

    }

}

0

나는 이것이 매우 오래된 실이라는 것을 알고 있지만 여전히 내 페니 가치를 추가하고 싶습니다.

간단한 16 진수 문자열을 이진 변환기로 코딩 해야하는 경우 다음과 같이하고 싶습니다.

public static byte[] hexToBinary(String s){

  /*
   * skipped any input validation code
   */

  byte[] data = new byte[s.length()/2];

  for( int i=0, j=0; 
       i<s.length() && j<data.length; 
       i+=2, j++)
  {
     data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
  }

  return data;
}

0

가장 깨끗한 해결책은 아닙니다. 그러나 그것은 나를 위해 일하고 잘 형식화되어 있습니다 :

private String createHexDump(byte[] msg, String description) {
    System.out.println();
    String result = "\n" + description;
    int currentIndex = 0;
    int printedIndex = 0;
    for(int i=0 ; i<msg.length ; i++){
        currentIndex++;
        if(i == 0){
            result += String.format("\n  %04x ", i);
        }
        if(i % 16 == 0 && i != 0){
            result += " | ";
            for(int j=(i-16) ; j<msg.length && j<i ; j++) {
                char characterToAdd = (char) msg[j];
                if (characterToAdd == '\n') {
                    characterToAdd = ' ';
                }
                result += characterToAdd;
                printedIndex++;
            }

            result += String.format("\n  %04x ", i);
        }

        result += String.format("%02x ", msg[i]);
    }

    if(currentIndex - printedIndex > 0){
        int leftOvers = currentIndex - printedIndex;
        for(int i=0 ; i<16-leftOvers ; i++){
            result += "   ";
        }

        result += " | ";

        for(int i=msg.length-leftOvers ; i<msg.length ; i++){
            char characterToAdd = (char) msg[i];
            if (characterToAdd == '\n') {
                characterToAdd = ' ';
            }
            result += characterToAdd;
        }
    }

    result += "\n";

    return result;
}

출력 :

  S -> C
    0000 0b 00 2e 06 4d 6f 72 69 74 7a 53 6f 6d 65 20 54  |  .Heyyy Some T
    0010 43 50 20 73 74 75 66 66 20 49 20 63 61 70 74 75  | CP stuff I captu
    0020 72 65 64 2e 2e 77 65 6c 6c 20 66 6f 72 6d 61 74  | red..well format
    0030 3f                                               | ?

-2

나는 당신을 위해 그것을 할 것이라고 생각합니다. 데이터를 문자열로 반환하는 비슷한 함수로 묶었습니다.

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

먼저 문자열을 대문자로 변환 할 필요가 없습니다. 둘째, 문자를 StringBuffer에 직접 추가 할 수있어 훨씬 효율적입니다.
마이클 마이어스

-2

저에게 이것은 해결책이었습니다 .HEX = "FF01"은 FF (255)와 01 (01)로 나뉩니다.

private static byte[] BytesEncode(String encoded) {
    //System.out.println(encoded.length());
    byte result[] = new byte[encoded.length() / 2];
    char enc[] = encoded.toUpperCase().toCharArray();
    String curr = "";
    for (int i = 0; i < encoded.length(); i=i+2) {
        curr = encoded.substring(i,i+2);
        System.out.println(curr);
        if(i==0){
            result[i]=((byte) Integer.parseInt(curr, 16));
        }else{
            result[i/2]=((byte) Integer.parseInt(curr, 16));
        }

    }
    return result;
}

이 질문은 한동안 대답되어 왔으며 몇 가지 좋은 대안이 있습니다. 불행히도이 시점에서 귀하의 답변은 크게 개선 된 가치를 제공하지 않습니다.
rfornal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.