简体   繁体   English

混合情况下base16(十六进制)解码的轻量级方法

[英]Lightweight method of decoding base16 (hexadecimals) of mixed case

Guava has interface that allows for base16/hexadecimal encoding and decoding. Guava具有允许base16 /十六进制编码和解码的接口。 Is there a lightweight method or trick for reading in hexadecimals that may contain mixed case? 是否存在一种轻量级的方法或技巧来读取可能包含混合大小写的十六进制?

With lightweight I mean: 轻量级的意思是:

  • no copying of the input string (so no toUpperCase() allowed) 不允许复制输入字符串(因此不允许toUpperCase()
  • few lines of code 几行代码
  • low amount of additional instructions (performant) 少量附加指令(性能良好)

The solution should not require an additional library on top of Java SE, and should be able to return relatively large byte arrays. 该解决方案不应在Java SE之上需要其他库,并且应能够返回相对较大的字节数组。

Code sample: 代码示例:

byte[] decoded = BaseEncoding.base16().decode("abCD");

will result in: 将导致:

com.google.common.io.BaseEncoding$DecodingException: Unrecognized character: a com.google.common.io.BaseEncoding $ DecodingException:无法识别的字符:a

using Guava version 15.0 (the latest release at the time of this question). 使用Guava 15.0版(此问题时的最新版本)。

Integer.parseInt(string, 16); does exactly what you describe. 完全符合您的描述。 If that's too easy for you, you may look into its implementation to learn how to do such a thing. 如果这对您来说太容易了,那么您可以研究其实现,以学习如何进行此操作。 But it's more than a few lines as it will handle all corner cases you might forget when doing it yourself. 但这不只是几行,因为它可以处理您自己做时可能会忘记的所有极端情况。 Eg the allowed maximum absolute value differs for positive and negative values. 例如,正负值允许的最大绝对值不同。 The only difference between an optimized hexadecimal and an arbitrary radix parsing is that you can use result<<=4; 优化的十六进制和任意基数解析之间的唯一区别是可以使用result<<=4; instead of result *= radix; 而不是result *= radix; for the hexadecimal case. 对于十六进制的情况。


Given your updated question the recommendation to look into that method still applies. 给定您更新的问题,建议仍应考虑使用该方法。 Decoding a sequence of bytes instead of an int will be even simpler: 解码字节序列而不是int会更加简单:

import static java.lang.Character.digit;
…

static byte[] decode(CharSequence cs)
{
  final int numCh = cs.length();
  if((numCh&1)!=0)
    throw new IllegalArgumentException("cs must have an even length");
  byte[] array=new byte[numCh>>1];
  for(int p=0; p<numCh; p+=2)
  {
    int hi=digit(cs.charAt(p), 16), lo=digit(cs.charAt(p+1), 16);
    if((hi|lo)<0)
      throw new IllegalArgumentException(cs+" contains non-hex characters");
    array[p>>1]=(byte)(hi<<4|lo);
  }
  return array;
}

I guess Apache commons-codec Hex class contains the methods you want. 我猜想Apache commons-codec Hex类包含您想要的方法。 The actual code for converting chars to digits is: 将字符转换为数字的实际代码是:

protected static int toDigit(final char ch, final int index) throws DecoderException {
    final int digit = Character.digit(ch, 16);
    if (digit == -1) {
        throw new DecoderException("Illegal hexadecimal character " + ch + " at index " + index);
    }
    return digit;
}

And the property Character.digit('F', 16) == Character.digit('f', 16) holds. 并且属性Character.digit('F', 16) == Character.digit('f', 16)成立。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM