将长整型转换为字节数组并将其添加到另一个数组中

51

我想将字节数组中的某些值更改为放置在最高有效位的长时间戳值。有人能告诉我最好的方法是什么吗?我不想逐位插入值,因为我认为这非常低效。

long time = System.currentTimeMillis();
Long timeStamp = new Long(time);
byte[] bArray = new byte[128];

我想要的是像这样的东西:

byte[0-63] = timeStamp.byteValue(); 

这种操作是否可能?编辑/插入字节数组的最佳方法是什么。由于byte是原始类型,我认为没有一些直接实现可以利用?

编辑:
似乎System.currentTimeMillis()Calendar.getTimeInMillis()快,因此用它替换上述代码。如果有错误,请纠正我。


这很有帮助:https://dev59.com/XW035IYBdhLWcg3weP7f - TacB0sS
我认为您的索引计数有误,请查看此问题:https://dev59.com/XW035IYBdhLWcg3weP7f - TacB0sS
5个回答

136

有多种方法可以实现:

  • 使用ByteBuffer(最佳选择-简洁易读):

byte[] bytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(someLong).array();
你还可以使用更冗长的DataOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(someLong);
dos.close();
byte[] longBytes = baos.toByteArray();
  • 最后,你可以手动执行此操作(从 Hector 代码中的 LongSerializer 获取)(阅读难度更高):

  • byte[] b = new byte[8];
    for (int i = 0; i < size; ++i) {
      b[i] = (byte) (l >> (size - i - 1 << 3));
    }
    
    然后你可以通过一个简单的循环将这些字节追加到你现有的数组中:
    // change this, if you want your long to start from 
    // a different position in the array
    int start = 0; 
    for (int i = 0; i < longBytes.length; i ++) {
       bytes[start + i] = longBytes[i];
    }
    

    5
    我发现我必须像这样设置ByteBuffer中的顺序,否则字节的顺序将与我所期望的相反 byte[] bytes = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(bits).array();。 - mR_fr0g
    2
    我认为Java通常是大端序的,而x86则是小端序的。 参考链接 - white_gecko
    5
    为了避免硬编码长整型的大小,我会使用allocate(Long.SIZE) - mike jones
    7
    请注意,Long.SIZE将给出用于表示Long的位数(http://docs.oracle.com/javase/6/docs/api/java/lang/Long.html#SIZE)。 您需要使用(Long.SIZE / Byte.SIZE)才能匹配上面的示例。 - overthink
    3
    Java 8引入了一个BYTES常量(http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#BYTES)来表示这个值。 - Max
    显示剩余2条评论

    22

    如果你想真正深入了解...

    public byte[] longToByteArray(long value) {
        return new byte[] {
            (byte) (value >> 56),
            (byte) (value >> 48),
            (byte) (value >> 40),
            (byte) (value >> 32),
            (byte) (value >> 24),
            (byte) (value >> 16),
            (byte) (value >> 8),
            (byte) value
        };
    }
    

    经过我的一些测试,上述的longToByteArray解决方案执行速度大约比ByteBuffer.allocate.putLong.array快5倍。 - mcfisty

    3

    对我而言,ByteBuffer和其他工具在时间上都比较昂贵。这里有两种方法可以使用:

    // 第一种方法(使用第二种方法),返回已分配并填充的数组

    public byte[] longToByteArray(long value) 
    {
            byte[] array = new byte[8];
    
            longToByteArray(value,array,0);
            return array;
    }
    

    // 如果你已经分配了缓冲区并想要将 long 类型数据写入数组的特定位置,那么这种方法很有用。

    public void longToByteArray(long value, byte[] array, int startFrom) 
    {
        for (int i=7; i>=0; i--)
        {
            array[startFrom+7-i] = (byte) (value >> i*8);
        }
    }
    

    0

    看起来你不能在子集中切割字节数组以插入某些内容,而不是逐个字节地进行操作。可以参考在Java中获取数组的一部分而不创建新的堆数组。基本上我会创建一个64字节的数组并将时间设置为它,然后将一个空的64字节数组附加到它上面。或者逐个字节地进行操作。


    0

    我正在更新这篇文章,因为我刚刚宣布了一个预发布版本的库,可以将长整型转换为字节数组(并且再次转换回来)。这个库非常小巧,并且可以将任何Java原始类型转换为字节数组。

    http://rschilling.wordpress.com/2013/09/26/pre-release-announcement-pend-oreille/ http://code.google.com/p/pend-oreille/

    如果您使用它,您可以执行诸如将长数组转换为字节数组之类的操作:

    Double[] doubles = new Double[1000];
    for (int i = 2; i < 1002; i++) {
        doubles[i - 2] = (double) i;
    }
    
    byte[] resultBytes1 = (byte[]) new PrimitiveHelper(PrimitiveUtil.unbox(doubles))
            .asType(byte[].class);
    

    您也可以将单个长整型值进行转换。

    byte[] resultBytes1 = (byte[]) new PrimitiveHelper(1000l)
            .asType(byte[].class);
    

    欢迎提供一些反馈。

    2013年10月4日更新: 我已经发布了库的生产http://rschilling.wordpress.com/2013/10/04/pend-oreille-official-1-0-release/


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接