16 진수로 채워진 바이트 배열이 있고 인쇄 할 수없는 요소가 많기 때문에 쉬운 방법으로 인쇄하는 것은 무의미합니다. 내가 필요한 것은 다음과 같은 형태의 정확한 16 진수 코드입니다.3a5f771c
16 진수로 채워진 바이트 배열이 있고 인쇄 할 수없는 요소가 많기 때문에 쉬운 방법으로 인쇄하는 것은 무의미합니다. 내가 필요한 것은 다음과 같은 형태의 정확한 16 진수 코드입니다.3a5f771c
답변:
토론에서 여기에 , 특히 이 대답이 내가 현재 사용하는 기능은 다음과 같습니다
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);
}
String printHexBinary(byte[])
및 등 유용한 도구가 많이 있습니다 byte[] parseHexBinary(String)
. printHexBinary
그러나이 답변의 기능보다 훨씬 (2 배) 느립니다. (소스를 확인했습니다 stringBuilder
. parseHexBinary
배열을 사용합니다.) 실제로 대부분의 경우 충분히 빠르며 이미 가지고있을 것입니다.
printHexBinary
.
javax.xml.bind.DataTypeConverter
Java 11에서 제거되었습니다.
아파치 코 몬즈 코덱 라이브러리는이 진수 작업의 바로 이런 종류의 작업을 수행하는 클래스.
import org.apache.commons.codec.binary.Hex;
String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );
import org.apache.commons.codec.*;
할 수 있습니다import org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
과 같이 사용할 수 있습니다 .String toHexString(byte[] data)
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 API 와 JAXB 런타임 을 설치해야합니다 .
사용법 예 :
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
결과는 다음과 같습니다.
000086003D
이 답변과 같은 이 하나 .
가장 간단한 솔루션, 외부 라이브러리 없음, 숫자 상수 없음 :
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();
}
완전성을위한 구아바 솔루션 :
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()
.
HashCode.fromBytes(checksum).toString()
이 간단한 oneliner는 나를 위해 일합니다.
String result = new BigInteger(1, inputBytes).toString(16);
편집-이것을 사용하면 선행 0이 제거되지만 내 유스 케이스에서 일했습니다. 지적 해 주셔서 감사합니다 @Voicu
다음은 단순 (한 줄짜리)에서 복잡한 (거대한 라이브러리)에 이르는 일반적인 옵션입니다. 성능에 관심이 있다면 아래의 마이크로 벤치 마크를 참조하십시오.
매우 간단한 해결책 중 하나는 BigInteger
의 16 진 표현 을 사용하는 것입니다 .
new BigInteger(1, someByteArray).toString(16)
참고이 손잡이 때문에 것을 수 없는 임의의 바이트 문자열 은 앞의 0을 생략합니다 -이 또는 당신이 (예를 들어 원하는 것을하지 않을 수 있습니다 000AE3
대 0AE3
3 바이트 입력). 이에 대해 매우 느린 또한 100 배 느린 다음 옵션에 비해.
대문자 / 소문자 및 엔디안을 지원하는 모든 기능을 갖춘 복사 및 붙여 넣기 가능한 코드 스 니펫 입니다. 메모리 복잡성을 최소화하고 성능을 최대화하도록 최적화되었으며 모든 최신 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 라이센스 및 디코더가 포함 된 전체 소스 코드는 여기 에서 찾을 수 있습니다 .
이전 프로젝트에서 작업하는 동안 Java에서 바이트로 작업하기위한이 작은 툴킷을 만들었습니다. 외부 종속성이 없으며 Java 7+와 호환됩니다. 여기에는 매우 빠르고 잘 테스트 된 HEX 인코더 / 디코더가 포함됩니다.
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Github 에서 확인할 수 있습니다 : bytes-java .
물론 좋은 'ol commons 코덱 '이 있습니다. ( 앞서 경고 의견 ) 위에서 설명한 프로젝트를 진행하는 동안 나는 코드를 분석했고 매우 실망했다. 많은 중복 구성되지 않은 코드, 더 이상 사용되지 않는 이국적인 코덱은 널리 사용되는 코덱 (특히 Base64)의 구현이 매우 적고 느리게 구현 된 경우에만 유용합니다. 그러므로 나는 당신이 그것을 사용하거나 대안을 원한다면 정보에 근거한 결정을 내릴 것입니다. 어쨌든, 여전히 사용하려면 코드 스 니펫이 있습니다.
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
더 자주 당신은 이미 구아바 를 의존으로 사용 하지 않습니다 . 그렇다면 다음을 사용하십시오.
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Spring Security 와 함께 Spring 프레임 워크 를 사용하는 경우 다음을 사용할 수 있습니다.
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
보안 프레임 워크 Bouncy Castle 을 이미 사용중인 경우 해당 Hex
유틸리티를 사용할 수 있습니다 .
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
이전 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. 여기 에서 전체 벤치 마크를 참조 하십시오 .
DataTypeConverter 클래스 사용javax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
해시와 같이 고정 길이에 다음과 같은 것을 사용합니다.
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
나는 여기에서 세 가지 다른 방법을 발견했다 : 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();
}
if (raw == null) return null
빨리 실패하지 않습니다. 왜 null
열쇠를 사용 하겠습니까?
룩업 테이블을 저장하는 데 드는 적은 비용으로이 구현은 간단하고 매우 빠릅니다.
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);
}
BYTE2HEX
간단한 for
주기로 어레이를 초기화하지 않겠습니까?
static { }
블록 으로 할당 될 수 있습니다 .
나는 이것을 사용하는 것을 선호한다 :
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);
}
허용되는 답변을 약간 더 융통성있게 적용합니다. 개인적으로, 나는 받아 들여진 대답 과이 과부하를 더 많은 맥락에서 사용할 수 있도록 유지합니다.
나는 보통 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();
}
StringBuilder buf = new StringBuilder(data.length * 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));
간단한 기능을 위해 유틸리티 병을 추가하는 것은 좋은 옵션이 아닙니다. 대신 자신의 유틸리티 클래스를 조립하십시오. 다음은 더 빠른 구현이 가능합니다.
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));
}
}
@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
이 페이지에서 해결되지 않은 솔루션을 찾을 수 없습니다
여기에 결함이없는 해결책이 있습니다 (그러나 다른 결함이 없다고 약속하지는 않습니다)
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);
}
내 솔루션은 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);
}
파이썬과 정확히 같은 바이트 배열을 찾고 있다면이 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=[])
다음은 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;
}
//...
}
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();
}
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);
}
toHexString(...)
이것이 당신이 찾고있는 것이라면 도움이 될 수 있는 방법이 있습니다. 또한 코드 문자열을String.format(...)
사용하여 깔끔한 서식 트릭을 수행 할 수 있습니다%2x
.