Dart TypedData e representação big / little endian

Dec 20 2020

Se eu executar o seguinte código:

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

Eu obtenho o seguinte resultado:

[1, 32768]

Uma vez que os valores originais eram

00000001 00000000 00000000 10000000
1        0        0        128

Eu esperava que eles fossem combinados assim:

0000000100000000 0000000010000000
256              128

Em vez disso, eu peguei este:

0000000000000001 1000000000000000
1                32768

Isso é pequeno endian, certo? Estou executando este código no meu Mac. A razão pela qual obtive o resultado acima é porque meu Mac usa little endian? Se eu executasse o mesmo código em um computador big endian, o resultado seria diferente? (Obtenho o mesmo resultado no DartPad, mas não sei em que máquina o DartPad está sendo executado.)

Respostas

3 ChristopherMoore Dec 20 2020 at 12:03

Sim, seria esperado um resultado diferente. Você obteria o resultado esperado em um sistema big endian. Seu método atual de visualizar seus dados de byte usa o endianness do sistema host. Isso inclui o DartPad, já que o código em execução no DartPad está sendo compilado para JS, que ainda está em execução no mesmo pequeno sistema endian.

Não há endianness definido para a linguagem Dart. No entanto, alguns métodos de visualização de dados de byte definem explicitamente um endianness como a ByteDataclasse.

1 Suragch Dec 28 2020 at 07:10

Aqui estão algumas informações adicionais para a resposta de Christopher Moore.

Você pode verificar o endianness do seu computador com o seguinte:

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

A maioria dos computadores pessoais usa arquitetura little endian, de modo que geralmente retorna true.

Você pode especificar o endianness com o qual deseja visualizar os dados usando em ByteDatavez 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'));
}

O resultado é:

0000000100000000 0000000010000000

Se você mudar Endian.bigpara Endian.littleo resultado será:

0000000000000001 1000000000000000

Você pode ler mais sobre isso aqui:

  • Trabalhando com bytes no Dart