我有一个字节数组充满十六进制数字和打印它的简单方式是相当没有意义的,因为有许多不可打印的元素。我需要的是精确的十六进制形式:3a5f771c
当前回答
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();
}
其他回答
Java 17最终包含HexFormat类,所以你可以简单地做:
HexFormat.of().formatHex(bytes);
它支持配置为小写/大写,分隔符,前缀,后缀等。
为了完整起见,一个番石榴解决方案:
import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);
现在十六进制是“48656c6c6f20776f726c64”。
我发现了三种不同的方法: 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();
}
我更喜欢用这个:
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);
}
它是对公认答案的稍微灵活的改编。 就我个人而言,我既保留了公认的答案,也保留了这个重载,以便在更多的环境中使用。
这是一个java.util。类似base64的实现,是不是很漂亮?
import java.util.Arrays;
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_CASE=new Encoder(false);
static final Encoder UPPER_CASE=new Encoder(true);
}
public static Encoder getEncoder(){
return Encoder.LOWER_CASE;
}
public static Encoder getUpperEncoder(){
return Encoder.UPPER_CASE;
}
public static class Decoder{
private static int maxIndex=102;
private static int[] toIndex;
static {
toIndex=new int[maxIndex+1];
Arrays.fill(toIndex, -1);
char[] chars={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'};
for(int i=0; i<chars.length; i++) {
toIndex[(int)chars[i]]=i;
}
}
public Decoder() {
}
public byte[] decode(String str) {
char[] value=str.toCharArray();
int start=0;
if(value.length>2 && value[0]=='0' && (value[1]=='x' || value[1]=='X')) {
start=2;
}
int byteLength=(value.length-start)/2; // ignore trailing odd char if exists
byte[] data=new byte[byteLength];
for(int i=start,j=0;i<value.length;i+=2,j++){
int i1;
int i2;
char c1=value[i];
char c2=value[i+1];
if(c1>maxIndex || (i1=toIndex[(int)c1])<0 || c2>maxIndex || (i2=toIndex[(int)c2])<0) {
throw new IllegalArgumentException("Invalid character at "+i);
}
data[j]=(byte)((i1<<4)+i2);
}
return data;
}
static final Decoder IGNORE_CASE=new Decoder();
}
public static Decoder getDecoder(){
return Decoder.IGNORE_CASE;
}
}
推荐文章
- 禁用IntelliJ星(包)导入?
- 面试问题:检查一个字符串是否是另一个字符串的旋转
- 将文件加载为InputStream的不同方法
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- Maven依赖Servlet 3.0 API?
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表
- Spring JPA选择特定的列