1

我正在尝试将 HEX 序列转换为以 ISO-8859-1、UTF-8 或 UTF-16BE 编码的字符串。也就是说,我有一个看起来像这样的字符串:"0422043504410442"这代表字符:"Test"在 UTF-16BE 中。

我用来在两种格式之间转换的代码是:

private static String hex2String(String hex, String encoding) throws UnsupportedEncodingException {
    char[] hexArray = hex.toCharArray();

    int length = hex.length() / 2;
    byte[] rawData = new byte[length];
    for(int i=0; i<length; i++){
        int high = Character.digit(hexArray[i*2], 16);
        int low = Character.digit(hexArray[i*2+1], 16);
        int value = (high << 4) | low;
        if( value > 127)
                value -= 256;
        rawData[i] = (byte) value;
    }
    return new String(rawData, encoding);
}

这对我来说似乎很好,但我对此仍有两个问题:

  1. 有没有更简单的方法(最好没有位处理)来进行这种转换?
  2. 我该如何解释这条线:int value = (high << 4) | low;

我熟悉位处理的基础知识,但完全不熟悉 Java 语法。我相信第一部分将所有位向左移动 4 步。尽管其余的我不明白,为什么它在这种特定情况下会有所帮助。

对于我的问题中的任何混淆,我深表歉意,如果我应该澄清任何事情,请告诉我。谢谢你。//Abeansits

4

3 回答 3

2

有没有更简单的方法(最好没有位处理)来进行这种转换?

我不知道 - 唯一的简化似乎是一次解析整个字节,而不是逐位解析(例如使用int value = Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);

public static byte[] hexToBytes(final String hex) {
  final byte[] bytes = new byte[hex.length() / 2];
  for (int i = 0; i < bytes.length; i++) {
    bytes[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
  }
  return bytes;
}

我该如何解释这一行:int value = (high << 4) | 低的;?

看看这个例子的最后两位数字(42):

int high = 4; // binary 0100
int low = 2; // binary 0010
int value = (high << 4) | low;

int value = (0100 << 4) | 0010; // shift 4 to left
int value = 01000000 | 0010; // bitwise or
int value = 01000010;
int value = 66; // 01000010 == 0x42 == 66
于 2009-10-27T15:22:17.213 回答
1

在这种情况下,您可以将 and 替换为<<and ,但我不推荐它。|*+

表达方式

int value = (high << 4) | low;

相当于

int value = high * 16 + low;

不需要减去 256 以获得介于 -128 和 127 之间的值。例如,简单地将 128 转换为一个字节将产生正确的结果。128的最低 8 位与 -128int具有相同的模式byte:0x80。

我会简单地写成:

rawData[i] = (byte) ((high << 4) | low);
于 2009-10-27T15:18:16.783 回答
1

有没有更简单的方法(最好没有位处理)来进行这种转换?

您可以在 Apache commons 中使用Hex类,但在内部,它会做同样的事情,也许会有细微的差别。

我该如何解释这条线:int value = (high << 4) | low;

这将两个十六进制数字(每个代表 4 位)组合成一个无符号 8 位值,存储为int. 接下来的两行将其转换为已签名的 Java byte

于 2009-10-27T15:25:28.127 回答