Tôi có một mảng byte chứa đầy các số hex và in nó một cách dễ dàng là khá vô nghĩa vì có nhiều yếu tố không thể in được. Những gì tôi cần là hexcode chính xác ở dạng:3a5f771c
Tôi có một mảng byte chứa đầy các số hex và in nó một cách dễ dàng là khá vô nghĩa vì có nhiều yếu tố không thể in được. Những gì tôi cần là hexcode chính xác ở dạng:3a5f771c
Câu trả lời:
Từ các cuộc thảo luận ở đây , và đặc biệt này câu trả lời, đây là chức năng Tôi hiện đang sử dụng:
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);
}
Điểm chuẩn nhỏ bé của riêng tôi (một triệu byte một nghìn lần, 256 byte 10 triệu lần) cho thấy nó nhanh hơn nhiều so với bất kỳ thay thế nào khác, khoảng một nửa thời gian trên các mảng dài. So với câu trả lời tôi đã lấy nó, chuyển sang ops bitwise --- như được đề xuất trong cuộc thảo luận --- cắt giảm khoảng 20% thời gian cho các mảng dài. (Chỉnh sửa: Khi tôi nói nó nhanh hơn các lựa chọn thay thế, ý tôi là mã thay thế được cung cấp trong các cuộc thảo luận. Hiệu suất tương đương với Commons Codec, sử dụng mã rất giống nhau.)
Phiên bản 2k20, liên quan đến chuỗi nhỏ gọn Java 9:
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[])
và byte[] parseHexBinary(String)
. printHexBinary
tuy nhiên, chậm hơn nhiều so với hàm trong câu trả lời này. (Tôi đã kiểm tra nguồn; nó sử dụng một stringBuilder
. parseHexBinary
Sử dụng một mảng.) Thực sự, mặc dù, đối với hầu hết các mục đích, nó đủ nhanh và bạn có thể đã có nó.
printHexBinary
?
javax.xml.bind.DataTypeConverter
đang bị xóa khỏi Java 11.
Thư viện Codec Apache Commons có một lớp Hex để thực hiện loại công việc này.
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.*;
bạn có thể làmimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
, với phương pháp này:String toHexString(byte[] data)
Phương thức javax.xml.bind.DatatypeConverter.printHexBinary()
, một phần của Kiến trúc Java cho liên kết XML (JAXB) , là một cách thuận tiện để chuyển đổi một byte[]
chuỗi hex. Các DatatypeConverter
lớp học cũng bao gồm nhiều phương pháp dữ liệu thao tác hữu ích khác.
Trong Java 8 trở về trước, JAXB là một phần của thư viện chuẩn Java. Nó không được chấp nhận với Java 9 và bị xóa bằng Java 11 , như một phần trong nỗ lực chuyển tất cả các gói Java EE vào các thư viện của riêng họ. Đó là một câu chuyện dài . Bây giờ, javax.xml.bind
không tồn tại và nếu bạn muốn sử dụng JAXB, có chứa DatatypeConverter
, bạn sẽ cần cài đặt API JAXB và JAXB Runtime từ Maven.
Ví dụ sử dụng:
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
Sẽ cho kết quả:
000086003D
Câu trả lời này giống như câu trả lời này .
Giải pháp đơn giản nhất, không có lib bên ngoài, không có hằng số:
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();
}
Một giải pháp ổi, cho đầy đủ:
import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);
Bây giờ hex
là "48656c6c6f20776f726c64"
.
new HashCode(bytes).toString()
.
HashCode.fromBytes(checksum).toString()
Công cụ oneliner đơn giản này hoạt động với tôi
String result = new BigInteger(1, inputBytes).toString(16);
EDIT - Sử dụng điều này sẽ loại bỏ các số không hàng đầu, nhưng hey đã làm việc cho trường hợp sử dụng của tôi. Cảm ơn @Voicu đã chỉ ra
Dưới đây là một số tùy chọn phổ biến được sắp xếp từ đơn giản (một lớp) đến phức tạp (thư viện khổng lồ). Nếu bạn quan tâm đến hiệu suất, hãy xem các điểm chuẩn vi mô dưới đây.
Một giải pháp rất đơn giản là sử dụng BigInteger
biểu diễn hex của:
new BigInteger(1, someByteArray).toString(16)
Lưu ý rằng vì điều này xử lý các số không phải là chuỗi byte tùy ý , nó sẽ bỏ qua các số 0 đứng đầu - điều này có thể hoặc không thể là những gì bạn muốn (ví dụ 000AE3
so 0AE3
với đầu vào 3 byte). Điều này cũng rất chậm, chậm hơn khoảng 100 lần so với tùy chọn tiếp theo.
Dưới đây là một đoạn mã đầy đủ, sao chép và có thể dán được hỗ trợ chữ hoa / chữ thường và chữ cuối . Nó được tối ưu hóa để giảm thiểu độ phức tạp của bộ nhớ và tối đa hóa hiệu suất và phải tương thích với tất cả các phiên bản Java hiện đại (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);
}
Mã nguồn đầy đủ với giấy phép và bộ giải mã Apache v2 có thể được tìm thấy ở đây .
Trong khi làm việc với dự án trước đó của tôi, tôi đã tạo ra bộ công cụ nhỏ này để làm việc với các byte trong Java. Nó không có phụ thuộc bên ngoài và tương thích với Java 7+. Nó bao gồm, trong số những người khác, một bộ giải mã / giải mã HEX được kiểm tra rất nhanh:
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Bạn có thể kiểm tra nó trên Github: byte-java .
Tất nhiên là có codec 'comm commons tốt . ( ý kiến cảnh báo trước ) Trong khi làm việc với dự án được nêu ở trên, tôi đã phân tích mã và khá thất vọng; rất nhiều mã không có tổ chức trùng lặp, các codec lỗi thời và kỳ lạ có lẽ chỉ hữu ích cho rất ít và quá nhiều triển khai các codec phổ biến (cụ thể là Base64). Do đó tôi sẽ đưa ra quyết định sáng suốt nếu bạn muốn sử dụng nó hoặc một giải pháp thay thế. Dù sao, nếu bạn vẫn muốn sử dụng nó, đây là đoạn mã:
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
Thường xuyên hơn không bạn đã có Guava như một phụ thuộc. Nếu vậy chỉ cần sử dụng:
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Nếu bạn sử dụng khung Spring với Spring Security, bạn có thể sử dụng như sau:
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
Nếu bạn đã sử dụng khung bảo mật Bouncy Castle, bạn có thể sử dụng tiện Hex
ích của nó :
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
Trong các phiên bản Java trước (8 trở xuống), mã Java cho JAXB được bao gồm dưới dạng phụ thuộc thời gian chạy. Vì Java 9 và mô đun hóa ghép hình, mã của bạn không thể truy cập mã khác ngoài mô-đun mà không cần khai báo rõ ràng. Vì vậy, hãy lưu ý nếu bạn nhận được một ngoại lệ như:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
khi chạy trên JVM với Java 9+. Nếu vậy thì chuyển đổi triển khai sang bất kỳ giải pháp thay thế nào ở trên. Xem thêm câu hỏi này .
Dưới đây là kết quả từ một mảng byte mã hóa chuẩn JMH đơn giản có kích thước khác nhau . Các giá trị là hoạt động mỗi giây, vì vậy cao hơn là tốt hơn. Lưu ý rằng điểm chuẩn vi mô rất thường không đại diện cho hành vi trong thế giới thực, vì vậy hãy lấy những kết quả này bằng một hạt muối.
| 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 |
Thông số kỹ thuật: JDK 8u202, i7-7700K, Win10, Ram 24GB. Xem điểm chuẩn đầy đủ ở đây .
Sử dụng lớp DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Tôi sẽ sử dụng một cái gì đó như thế này cho chiều dài cố định, như băm:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
Tôi đã tìm thấy ba cách khác nhau ở đây: http://www.rgagnon.com/javadetails/java-0596.html
Người thanh lịch nhất, như anh ấy cũng lưu ý, tôi nghĩ là cái này:
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
không thất bại nhanh Tại sao bạn sẽ sử dụng một null
chìa khóa?
Với chi phí nhỏ để lưu trữ bảng tra cứu, việc thực hiện này rất đơn giản và rất nhanh.
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
mảng với một for
chu kỳ đơn giản ?
static { }
khối.
Còn cái này thì sao?
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;
}
Tôi thích sử dụng này:
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);
}
Nó là một chút thích ứng linh hoạt hơn của câu trả lời được chấp nhận. Cá nhân, tôi giữ cả câu trả lời được chấp nhận và sự quá tải này cùng với nó, có thể sử dụng trong nhiều ngữ cảnh hơn.
Tôi thường sử dụng phương pháp sau cho câu lệnh debuf, nhưng tôi không biết liệu đó có phải là cách tốt nhất để làm hay không
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);
.
Ok, có rất nhiều cách để làm điều này, nhưng nếu bạn quyết định sử dụng thư viện, tôi sẽ đề nghị chọc vào dự án của bạn để xem có gì đã được thực hiện trong thư viện đã là một phần của dự án của bạn trước khi thêm thư viện mới không chỉ để làm điều này Ví dụ: nếu bạn chưa có
org.apache.commons.codec.binary.Hex
có lẽ bạn có ...
org.apache.xerces.impl.dv.util.HexBin
Nếu bạn đang sử dụng khung bảo mật Spring, bạn có thể sử dụng:
import org.springframework.security.crypto.codec.Hex
final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
Thêm một jar tiện ích cho chức năng đơn giản là lựa chọn không tốt. Thay vào đó lắp ráp các lớp tiện ích của riêng bạn. sau đây có thể thực hiện nhanh hơn.
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));
}
}
Một biến thể nhỏ của giải pháp được đề xuất bởi @maybewecouldstealavan, cho phép bạn kết hợp trực quan N byte với nhau trong chuỗi hex đầu ra:
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();
}
Đó là:
bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E
bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E
Không thể tìm thấy bất kỳ giải pháp nào trên trang này mà không
Đây là một giải pháp không có sai sót ở trên (không có lời hứa nào của tôi không có lỗi nào khác)
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()));
}
}
Tôi không thể có được điều này dưới 62 opcodes, nhưng nếu bạn có thể sống mà không có 0 đệm trong trường hợp byte đầu tiên nhỏ hơn 0x10, thì giải pháp sau chỉ sử dụng 23 opcode. Thực sự cho thấy các giải pháp "dễ tự thực hiện" như "pad với số 0 nếu độ dài chuỗi là số lẻ" có thể trở nên khá tốn kém nếu triển khai riêng không có sẵn (hoặc trong trường hợp này, nếu BigInteger có tùy chọn tiền tố với số không trong 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);
}
Giải pháp của tôi dựa trên giải pháp của mayweCouldStealAVan, nhưng không dựa vào bất kỳ bảng tra cứu được phân bổ bổ sung nào. Nó không sử dụng bất kỳ hack 'int-to-char' nào (thực ra là Character.forDigit()
vậy, thực hiện một số so sánh để kiểm tra xem chữ số thực sự là gì) và do đó có thể chậm hơn một chút. Xin vui lòng sử dụng nó bất cứ nơi nào bạn muốn. Chúc mừng.
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);
}
Nếu bạn đang tìm kiếm một mảng byte chính xác như thế này cho python, tôi đã chuyển đổi triển khai Java này thành python.
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=[])
Đây là một java.util.Base64
triển khai giống như (một phần), nó không đẹp sao?
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(...)
phương pháp có thể giúp ích nếu đây là những gì bạn đang tìm kiếm. CũngString.format(...)
có thể thực hiện một số thủ thuật định dạng gọn gàng bằng cách sử dụng%2x
chuỗi mã.