Android 开发小记:ByteArrayBuilder
本文最后更新于 828 天前,其中的信息可能已经有所发展或是发生改变。

在 Android 开发时,有时候会遇到创建 byte 数组的需求。创建 byte 数组和创建其他数组一样,没有什么好稀奇的,但是麻烦的地方在于我负责的项目还在使用 Java 语言,并且由于一些特殊原因不能转为 Kotlin。然而 Java 中数组是不能扩展长度的,因此必须提前设计好数组的长度,然后再进行填充。并且填充数组也非常的麻烦,代码也非常难以阅读,到最后可能也搞不清楚生成的 byte 数组变成什么样了。

因此迫于形势,我只好自己动手,设计一个 ByteArrayBuilder 类,用来组装 byte 数组。其源码如下:

public class ByteArrayBuilder {
    private int totalLength = 0;
    private final List<ByteArrayEntry> entryList = new LinkedList<>();

    public ByteArrayBuilder() {}

    public ByteArrayBuilder(byte[] array) {
        append(array);
    }

    public ByteArrayBuilder append(byte value) {
        return append(new byte[]{ value });
    }

    public ByteArrayBuilder append(int value) {
        return append((byte) value);
    }

    public ByteArrayBuilder append(byte[] array) {
        return append(array.length, array);
    }

    public ByteArrayBuilder append(int length, byte value) {
        return append(length, new byte[]{ value });
    }

    public ByteArrayBuilder append(int length, int value) {
        return append(length, (byte) value);
    }

    public ByteArrayBuilder append(int length, byte[] array) {
        return append(length, true, array);
    }

    public ByteArrayBuilder append(int length, boolean isPaddingRight, byte value) {
        return append(length, isPaddingRight, new byte[]{ value });
    }

    public ByteArrayBuilder append(int length, boolean isPaddingRight, int value) {
        return append(length, isPaddingRight, (byte) value);
    }

    public ByteArrayBuilder append(int length, boolean isPaddingRight, byte[] array) {
        if (length <= 0) {
            // length cannot be negative or zero, ignore
            return this;
        }
        if (length + totalLength < 0) {
            // overflow, cannot append, ignore
            return this;
        }

        byte[] data = array;

        if (array == null) {
            // empty array
            data = new byte[0];
        }

        int srcPosition = 0;
        int destPosition = 0;

        if (length < data.length) {
            // need cut
            if (isPaddingRight) {
                srcPosition = data.length - length;
            }
        }

        if (length > data.length) {
            // need fill
            if (isPaddingRight) {
                destPosition = length - data.length;
            }
        }

        int copyLength = Math.min(length, data.length);

        entryList.add(new ByteArrayEntry(data, length, srcPosition, destPosition, copyLength));
        totalLength += length;
        return this;
    }

    public byte[] build() {
        byte[] output = new byte[totalLength];
        int index = 0;
        for (ByteArrayEntry entry : entryList) {
            // copy data
            System.arraycopy(entry.data, entry.srcPosition, output,
                    index + entry.destPosition, entry.copyLength);

            index += entry.length;
        }
        return output;
    }

    private static class ByteArrayEntry {
        private final byte[] data;
        private final int length;
        private final int srcPosition;
        private final int destPosition;
        private final int copyLength;

        public ByteArrayEntry(byte[] data, int length, int srcPosition, int destPosition, int copyLength) {
            this.data = data;
            this.length = length;
            this.srcPosition = srcPosition;
            this.destPosition = destPosition;
            this.copyLength = copyLength;
        }
    }
}

这样一套代码可以说非常简单了,基本上不需要任何解释。使用起来也非常简单:

byte[] result = new ByteArrayBuilder()
        .append(0x01)
        .append(2, 0x02)
        .append(new byte[]{0x03, 0x03, 0x03})
        .append(4, false, new byte[]{0x04, 0x04})
        .build();
// result = {0x01, 0x00, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x00, 0x00}

就是这样。

暂无评论

发送评论 编辑评论

上一篇
下一篇