Dart TypedData y representación de endian grande / pequeño

Dec 20 2020

Si ejecuto el siguiente código:

Uint8List bytes = Uint8List.fromList([1, 0, 0, 128]);
ByteBuffer byteBuffer = bytes.buffer;
Uint16List sixteenBitList = byteBuffer.asUint16List();
print(sixteenBitList);

Obtengo el siguiente resultado:

[1, 32768]

Dado que los valores originales eran

00000001 00000000 00000000 10000000
1        0        0        128

Hubiera esperado que se combinaran así:

0000000100000000 0000000010000000
256              128

En cambio, obtuve esto:

0000000000000001 1000000000000000
1                32768

Eso es pequeño endian, ¿verdad? Estoy ejecutando este código en mi Mac. ¿La razón por la que obtuve el resultado anterior es porque mi Mac usa little endian? Si ejecuto el mismo código en una computadora Big Endian, ¿daría un resultado diferente? (Obtengo el mismo resultado en DartPad, pero no sé en qué máquina se está ejecutando DartPad).

Respuestas

3 ChristopherMoore Dec 20 2020 at 12:03

Sí, se esperaría que diera un resultado diferente. Obtendría el resultado esperado en un sistema big endian. Su método actual de ver sus datos de bytes utiliza el endianness del sistema host. Esto incluye DartPad ya que el código que se ejecuta en DartPad se está compilando en JS, que todavía se ejecuta en ese mismo sistema little endian.

No hay un endianness establecido para el lenguaje Dart. Sin embargo, algunos métodos de visualización de datos de bytes establecen explícitamente un endianness como la ByteDataclase.

1 Suragch Dec 28 2020 at 07:10

Aquí hay información adicional a la respuesta de Christopher Moore.

Puede verificar la endianidad de su computadora con lo siguiente:

print(Endian.host == Endian.little);

La mayoría de las computadoras personales usan una arquitectura little endian, por lo que generalmente regresará true.

Puede especificar el endianness con el que desea ver los datos utilizando en ByteDatalugar de BytesBuffer:

import 'dart:typed_data';

void main() {
  Uint8List byteList = Uint8List.fromList([1, 0, 0, 128]);
  ByteData byteData = ByteData.sublistView(byteList);

  int value = byteData.getUint16(0, Endian.big);
  print(value.toRadixString(2).padLeft(16, '0'));
  
  value = byteData.getUint16(2, Endian.big);
  print(value.toRadixString(2).padLeft(16, '0'));
}

El resultado es:

0000000100000000 0000000010000000

Si cambia Endian.bigal Endian.littleresultado será:

0000000000000001 1000000000000000

Puedes leer más sobre esto aquí:

  • Trabajando con bytes en Dart