【问题标题】:How to convert a Byte Array to an Int Array without copying如何在不复制的情况下将字节数组转换为整数数组
【发布时间】:2020-08-14 18:38:08
【问题描述】:

已经有一个solution,但它涉及内存复制。我想要一个不涉及内存复制的解决方案。在这种情况下,保证输入字节数组 (byte[]) 必须包含 4 的倍数的字节数,以便可以将其转换为整数数组 (int[]) 而无需填充/重新分配。

这在 C 中很容易做到。我想要在 Java 中做类似的事情(特别是在 Android 上)。这是C版本:

// input byte array
// note that the number of bytes (char) is the multiple of 4 (i.e., sizeof(int)).
char* byte_array = calloc(100, sizeof(int));
byte_array[0] = 'a'; // 0x61
byte_array[1] = 'b'; // 0x62
byte_array[2] = 'c'; // 0x63
byte_array[3] = 'd'; // 0x64

// converting it to an integer array
// note that it does not involve memory copying
int* integer_array = (int *) byte_array;

// printing the first integer of the integer array
// it will print: 0x64636261 or 0x61626364, depending on the endianness 
printf("0x%X\n", integer_array[0]);

真的可以在 Java 中做类似的事情(即不复制内存)吗?

【问题讨论】:

    标签: java android arrays


    【解决方案1】:

    不,这是不可能的。

    Java 中的数组不能轻易地重新解释为其他类型。数组对象的内存布局包括指向数组类的指针和数组的长度。没有任何操作可以让您覆盖现有数组的类指针和长度字段。

    您可以使用 java.nio 中的“缓冲区”对象执行类似的操作,但实际上并不相同。您可以创建一个包装字节数组的 ByteBuffer 对象。然后,您可以从字节缓冲区中获取 IntBuffer“视图”。没有数据被复制,因为这些对象只是访问字节数组中数据的视图。这会打印出0x64636261:

    byte[] byte_array = new byte[128];
    byte_array[0] = 'a'; // 0x61
    byte_array[1] = 'b'; // 0x62
    byte_array[2] = 'c'; // 0x63
    byte_array[3] = 'd'; // 0x64
    
    ByteBuffer byteBuffer = ByteBuffer.wrap(byte_array);
    // set CPU-native byte order to enable optimizations
    byteBuffer.order(ByteOrder.nativeOrder());
    
    IntBuffer intBuffer = byteBuffer.asIntBuffer();
    System.out.printf("0x%X\n", intBuffer.get(0));
    

    【讨论】:

      【解决方案2】:

      您可以在不复制的情况下转换为List<Integer>,而不是转换为int[]

      public class ByteArrayIntList extends AbstractList<Integer> {
      
          private final int size;
          private final IntBuffer intBuffer;
      
          public ByteArrayIntList(byte[] array) {
              if (array.length % 4 != 0)
                  throw new IllegalArgumentException("array");
              this.size = array.length / 4;
              this.intBuffer = ByteBuffer.wrap(array).asIntBuffer();
          }
      
          @Override
          public Integer get(int index) {
              return intBuffer.get(index);
          }
      
          @Override
          public Integer set(int index, Integer element) {
              int oldValue = get(index);
              intBuffer.put(index, element);
              return oldValue;
          }
      
          @Override
          public int size() {
              return size;
          }
      
      }
      

      byte[] byteArray = {'a', 'b', 'c', 'd'};
      System.out.println(Arrays.toString(byteArray));
      ByteArrayIntList list = new ByteArrayIntList(byteArray);
      System.out.printf("list.get(0) = 0x%08x%n", list.get(0));
      

      输出:

      list.get(0) = 0x61626364
      

      修改这个列表会修改原来的字节数组。

      list.set(0, 0x12345678);
      System.out.print("byteArray = ");
      for (int i = 0; i < byteArray.length; ++i)
          System.out.printf("0x%02x ", byteArray[i]);
      System.out.println();
      

      输出:

      byteArray = 0x12 0x34 0x56 0x78
      

      您可以将.sort().stream().iterator() 应用到ByteArrayIntList。 由于ByteArrayIntList是一个固定长度的列表,.add()会抛出UnsupportedOperationException

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        • 2015-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多