【问题标题】:byte array with variable length to number可变长度到数字的字节数组
【发布时间】:2016-12-26 11:33:08
【问题描述】:

我需要将数字转换为字节数组,然后再转换回数字。 问题是字节数​​组是可变大小的,所以我需要根据他的字节长度转换一个数字,我想出的方法是:(Java)

private static byte[] toArray(long value, int bytes) {
    byte[] res = new byte[bytes];

    final int max = bytes*8;
    for(int i = 1; i <= bytes; i++)
        res[i - 1] = (byte) (value >> (max - 8 * i));

    return res;
}

private static long toLong(byte[] value) {
    long res = 0;

    for (byte b : value)
        res = (res << 8) | (b & 0xff);

    return res;
}

这里我使用 long 因为 8 是我们可以使用的最大字节数。 这种方法对正数非常有效,但我似乎无法使用负数进行解码。

编辑:为了测试这一点,我尝试处理值 Integer.MIN_VALUE + 1 (-2147483647) 和 4 个字节

【问题讨论】:

  • 不知道您的问题现在是否已解决,但是...看看我的答案是否可以帮助您处理较大的负值。

标签: java arrays byte data-conversion


【解决方案1】:

在接受这个作为可行的解决方案后,提问者进一步做了一些 优化。
我已经包含了自己的
linked code 下面为 参考:

private static long toLong(byte[] value) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    final byte val = (byte) (value[0] < 0 ? 0xFF : 0);

    for(int i = value.length; i < Long.BYTES; i++)
        buffer.put(val);

    buffer.put(value);
    return buffer.getLong(0);
}

老答案

edit:基于 cmets(更好地理解问题)

要让您的 toLong 函数同时处理 negative 和 positive 数字,请尝试以下操作:

private static long toLong(byte[] value) 
{
    long res = 0;
    int tempInt = 0;
    String tempStr = ""; //holds temp string Hex values

    tempStr = bytesToHex(value);

    if (value[0] < 0 ) 
    { 
        tempInt = value.length;
        for (int i=tempInt; i<8; i++) { tempStr = ("FF" + tempStr); }

        res = Long.parseUnsignedLong(tempStr, 16); 
    }
    else { res = Long.parseLong(tempStr, 16); }

    return res;

}

下面是相关的bytesToHex 函数(重构为可与任何byte[] 输入一起工作...)

public static String bytesToHex(byte[] bytes)
{ String tempStr = ""; tempStr = DatatypeConverter.printHexBinary(bytes); return tempStr; }


【讨论】:

  • 这不是可变的,我不能说“把这个数字放在 5 个字节中”或“从这 5 个字节中获取我的数字”
  • 你不应该只输入 5 个字节。所有语言/操作系统一次读取为 1、2、4 或 8 个字节。如果您的号码只需要 5 个字节,那么您已经处于实际上必须读取为 8 个字节的情况。使用bit-shifting 将 40 位(5 字节)保留在 Array 的一侧,并用零位填充剩余的 3 字节槽。
  • 我已经做过类似的事情(见我的问题),但问题是我不知道如何处理负值
  • 我使用我的方法和你的 bytesToHex 进行了测试: byte[] toArr = toArray(Integer.MIN_VALUE + 1, 4); System.out.println(bytesToHex(toArr)); System.out.println(toLong(toArr));结果:“80000001”和“2147483649”,否定性丢失:/
  • 谢谢你的回答,我写了一个稍微优化的版本(字符串操作不是很快)这里是使用java的ByteBuffer的新版本pastebin.com/JKy8s5A6
【解决方案2】:

看看 Apache Common Conversion.intToByteArray util 方法。

JavaDoc:

使用默认 (little endian, Lsb0) 字节和位顺序将 int 转换为字节数组

【讨论】:

  • 刚刚测试过:
  • long v = Integer.MIN_VALUE + 1; byte[] res = new byte[4]; longToByteArray(v, 0, res, 0, 4); long out = byteArrayToLong(res, 0, 0L, 0, 4); System.out.println(out); 消极情绪丢失
  • @SnowyCoder 如果此答案有效,则使用✓ 图标将其标记为解决方案。
  • @VC.One 这个答案不起作用,正如第二条评论中所写,它失去了数字否定性
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-13
  • 2014-04-03
相关资源
最近更新 更多