将多个字节数组复制到一个大的字节数组中

35

我有一个大的byte[]数组和许多小的byte数组(大数组的长度是小数组长度之和)。是否有一种快速的方法可以从起始位置到结束位置将一个数组复制到另一个数组,而不是手动使用循环逐字节进行操作?

5个回答

59
您可以使用ByteBuffer
ByteBuffer target = ByteBuffer.wrap(bigByteArray);
target.put(small1);
target.put(small2);
...;

很确定这个内部会使用其他答案建议的类似代码。点赞,通常最好使用内置方法而不是重新发明轮子。 - cthulhu
被踩了。这并没有考虑到当大数组的最终长度在传递第一部分数组时是未知的情况。 - Mark Jeronimus
2
@Zom-B 这个问题开头是“我有一个大的字节数组”,所以看起来数组的大小已经事先知道了。 - josefx
如果你需要一个给定大小的数组,但是还没有它,请使用ByteBuffer.allocate(size)。然后,在所有target.put()调用之后,调用target.getArray() - Evgeny Veretennikov

25

使用System.arraycopy()

你还可以应用我之前回答Stack Overflow中提供的解决方法。请注意,对于像byte这样的基本类型,您需要生成单独的版本(每个基本类型一个版本),因为泛型在那里不起作用。


如果您让它接受Object参数而不是两个T[],那么它也可以用于原始类型。但这当然意味着没有编译时检查。 - Sean Patrick Floyd
1
@Sean:不幸的是,没有接受“Object”作为参数的“Arrays.copyOf()”方法。 - Joachim Sauer
啊,我把 System.arrayCopy() 弄混了,感到困惑。 - Sean Patrick Floyd
这个方法是 System 的,感觉有点奇怪! - Dori

13
或者你可以使用一个ByteArrayOutputStream(虽然它为你创建了结果数组,而不是像你要求的那样复制到现有数组中)。
public byte[] concatenateByteArrays(List<byte[]> blocks) {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    for (byte[] b : blocks) {
        os.write(b, 0, b.length);
    }
    return os.toByteArray();
}

只需观看此链接https://android.googlesource.com/platform/libcore/+/5d930ca/luni/src/main/java/java/io/ByteArrayOutputStream.java你的代码非常低效。 - Master

6

示例实现

public static void copySmallArraysToBigArray(final byte[][] smallArrays,
    final byte[] bigArray){
    int currentOffset = 0;
    for(final byte[] currentArray : smallArrays){
        System.arraycopy(
            currentArray, 0,
            bigArray, currentOffset,
            currentArray.length
        );
        currentOffset += currentArray.length;
    }
}

测试代码

public static void main(final String[] args){
    final byte[][] smallArrays =
        {
           "The"    .getBytes(),
           " Quick" .getBytes(),
           " Brown" .getBytes(),
           " Fox"   .getBytes()
        };
    final byte[] bigArray = "The Small Mauve Cat".getBytes();
    copySmallArraysToBigArray(smallArrays, bigArray);
    System.out.println(new String(bigArray));
}

输出:

快速棕色狐狸


我会移除检查和抛出异常的代码,因为当索引超出范围时,System.arraycopy() 已经会抛出 IndexOutOfBoundsException 异常(而且该异常提供了更多信息)。 - Joachim Sauer
@sean:请在下一个样例中使用getBytes(Charset.forName("ASCII"))或类似方法(因为getBytes()的字符编码依赖于运行时系统)。 - Maarten Bodewes

2

这里有另一种解决方案,也使用了ByteBuffer

public static byte[] toByteArray(List<byte[]> bytesList)
{
    int size = 0;

    for (byte[] bytes : bytesList)
    {
        size += bytes.length;
    }

    ByteBuffer byteBuffer = ByteBuffer.allocate(size);

    for (byte[] bytes : bytesList)
    {
        byteBuffer.put(bytes);
    }

    return byteBuffer.array();
}

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