如何将 byte[] 图像拆分为每个字节最大 10000 长度的多个 byte[]?

How do I split a byte[] image into multiple byte[] of a maximum 10000 length each byte?

我在这里找到了很多答案,但其中 none 确实是我想要的。

假设我可以发送最大尺寸为 10000 的图像,因此如果我发送例如 25796 的图像,我需要将 byte[] 拆分为 3、10000 + 10000 + 5796。

所以我想我应该有一个接收字节 [] 和 returns 列表的方法 对吗?

我在循环中使用 Arrays.copyOfRange,但最后的字节很难获取(例如最后的 5796)。

希望有人能帮助我。

非常感谢!

编辑:

我想我已经成功了,我需要测试更多的案例,但明天我会这样做,因为我很累 rn。如果一切正常,我会 post 作为答案。

这是我现在拥有的:(有一个额外的方法来检查最后字节是否匹配)

public List<byte[]> byteSplitter(byte[] origin) {


    List<byte[]> byteList = new LinkedList<>();


    int splitIndex = 10000;
    int currBytes = 0;
    boolean bytesHasSameLength = false;
    while (!bytesHasSameLength) {

        if (splitIndex > origin.length) {
            splitIndex = origin.length;
            bytesHasSameLength = true;
        }

        byteList.add(Arrays.copyOfRange(origin, currBytes, splitIndex));

        currBytes = splitIndex;
        splitIndex += 10000;

    }


    return byteList;
}

public void appendByteAndCheckMatch(byte[] bytes, List<byte[]> byteList) {

    ByteArrayOutputStream output = new ByteArrayOutputStream();

    for (byte[] b : byteList) {
        try {
            output.write(b);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    byte[] bytesFromList = output.toByteArray();

    System.out.println("list bytes: " + bytesFromList.length);
    System.out.println("request bytes: " + bytes.length);

    if (Arrays.equals(bytesFromList, bytes))
        System.out.println("bytes are equals");
    else
        System.out.println("bytes are different");
}

结果:

列表字节:25796 请求字节:25796 字节等于

你可以像这样很容易地做到这一点。结束位置调整为不超过原尺寸

byte[] array = new byte[123039];
int bufSize = 10_000;
int end = 0;
for (int offset = 0; offset <= array.length; offset+= bufSize) {
    end+=bufSize;
    if (end >= array.length) {
        end = array.length;
    }
    byte[] arr = Arrays.copyOfRange(array, offset, end  );
    // do something with arr
}

您需要以“最大长度”为增量遍历原始数组,同时还要确保您不会超过数组的长度。这可以通过单个 for 循环来完成。例如:

public static List<byte[]> split(byte[] source, int maxLength) {
  Objects.requireNonNull(source);
  if (maxLength <= 0) {
    throw new IllegalArgumentException("maxLength <= 0");
  }

  List<byte[]> result = new ArrayList<>();

  for (int from = 0; from < source.length; from += maxLength) {
    int to = Math.min(from + maxLength, source.length);
    byte[] range = Arrays.copyOfRange(source, from, to);
    result.add(range);
  }

  return result;
}

这将处理 maxLength 的任何非零正值,即使该值大于或等于 source 的长度。

请注意,这是将数据从原始数组复制到新数组中。这意味着原始数组被有效复制,这可能会或可能不会被接受,因为您现在至少消耗了两倍的内存(尽管您可能会丢弃原始数组)。如果您的用例允许,并且您需要使用尽可能少的内存,那么请考虑 ByteBuffer.

public static List<ByteBuffer> split(byte[] source, int maxLength) {
  return split(ByteBuffer.wrap(source), maxLength);
}

public static List<ByteBuffer> split(ByteBuffer source, int maxLength) {
  Objects.requireNonNull(source);
  if (maxLength <= 0) {
    throw new IllegalArgumentException("maxLength <= 0");
  }

  List<ByteBuffer> result = new ArrayList<>();

  for (int index = source.position(); index < source.limit(); index += maxLength) {
    int length = Math.min(maxLength, source.limit() - index);
    ByteBuffer slice = source.slice(index, length);
    result.add(slice);
  }

  return result;
}

列表中返回的每个 ByteBuffer 使用相同的支持数据。当然,这样做的一个后果是对源数据的更改会影响每个缓冲区。尽管如果你愿意,你可以将缓冲区设置为只读(请记住,如果你包装一个数组然后直接更改数组也会影响缓冲区,并且你不能将数组设置为只读)。