获取int的字节表示,仅使用3个字节

时间:2012-07-06 23:53:13

标签: java hadoop bytearray hbase binary-data

获取byte[]的字节表示(即int),但只使用3个字节(而不是4个字节),这是一种很好的,可读的方法吗?我正在使用Hadoop / Hbase,他们的Bytes实用程序类具有toBytes函数,但总是使用4个字节。

理想情况下,我还想要一种好的,可读的编码方式,尽可能少的字节,即如果数字适合一个字节,那么只使用一个。

请注意我将其存储在byte[]中,因此我知道数组的长度,因此不需要可变长度编码。这是关于找到一种优雅的方式进行演员表。

6 个答案:

答案 0 :(得分:4)

对此的一般解决方案是不可能的。

如果可能,您可以迭代地应用该函数以获得无限制的数据压缩。

您的域可能会对允许将它们压缩为24位的整数有一些限制。如果存在此类限制,请在问题中解释。

常见的可变大小编码是将每个字节的7位用于数据,将高位用作标志,以指示当前字节何时是最后一个。


您可以预测int上使用a utility methodInteger进行编码所需的字节数:

int n = 4 - Integer.numberOfLeadingZeros(x) / 8;
byte[] enc = new byte[n];
while (n-- > 0) 
  enc[n] = (byte) ((x >>> (n * 8)) & 0xFF);

请注意,这会将0编码为空数组,将其他值编码为 little-endian 格式。通过一些操作可以轻松修改这些方面。

答案 1 :(得分:1)

如果需要表示整个2 ^ 32个现有的4字节整数,则需要选择:

  • 固定大小的表示,总是使用4个字节;或
  • 可变大小的表示,对某些数字使用至少5个字节。

看看UTF-8如何编码Unicode字符,您可能会获得一些见解。 (你使用一些简短的前缀来描述必须为该unicode字符读取多少字节,然后你读取那么多字节并解释它们。)

答案 2 :(得分:1)

尝试使用ByteBuffer。如果需要,您甚至可以设置小端模式:

int exampleInt = 0x11FFFFFF;
ByteBuffer buf = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
final byte[] threeByteBuffer = new byte[3];
buf.putInt(exampleInt);
buf.position(1);
buf.get(threeByteBuffer);

或签名最短的Big Endian:

BigInteger bi = BigInteger.valueOf(exampleInt);
final byte[] shortestSigned = bi.toByteArray();

答案 3 :(得分:0)

int转换为4 byte s数组,并迭代它,如果每个高位字节为零,则将其从数组中删除。

类似的东西:

byte[] bytes = toBytes(myInt);
int neededBytes = 4;
for (;neededBytes > 1; i--) {
    if (bytes[neededBytes - 1] != 0) {
       break;
    }
}

byte[] result = new byte[neededBytes];
// then just use array copy to copy first neededBytes to result.

答案 4 :(得分:0)

你可以从这样的事情开始:

byte[] Convert(int i)
{  // warning: untested
  if (i == 0)
    return new byte[0];
  if (i > 0 && i < 256)
    return new byte[]{(byte)i};
  if (i > 0 && i < 256 * 256)
    return new byte[]{(byte)i, (byte)(i >> 8)};
  if (i > 0 && i < 256 * 256 * 256)
    return new byte[]{(byte)i, (byte)(i >> 8), (byte)(i >> 16)};
  return new byte[]{(byte)i, (byte)(i >> 8), (byte)(i >> 16), (byte)(i >> 24)};
}

你需要决定你是想成为小端还是大端。请注意,负数以4个字节编码。

答案 5 :(得分:0)

如果我理解你真的那么,拼命想要节省空间,即使以牺牲神秘的位洗牌为代价:任何阵列类型都是不必要的奢侈品,因为你不能使用少于一个整数字节的长度=寻址空间256知道最多需要4个。所以我会为长度和符号标志保留4位,并将其余部分与该字节数对齐。如果你的MSB小于128,你甚至可以再保存一个字节。我认为符号标志对于能够以小于4个字节表示负数的能力很有用。最好每次都有位(即使是正数),而不是4字节的开销来表示-1。

无论如何,在您对数据集进行一些统计,实际可压缩的整数数量以及压缩开销是否值得付出努力之前,这一切都很薄。