Dart TypedData i reprezentacja dużego / małego endianu

Dec 20 2020

Jeśli uruchomię następujący kod:

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

Otrzymuję następujący wynik:

[1, 32768]

Ponieważ oryginalne wartości były

00000001 00000000 00000000 10000000
1        0        0        128

Spodziewałbym się, że zostaną połączone w ten sposób:

0000000100000000 0000000010000000
256              128

Zamiast tego dostałem to:

0000000000000001 1000000000000000
1                32768

To trochę endian, prawda? Uruchamiam ten kod na moim Macu. Czy jest to powód, dla którego otrzymałem powyższy wynik, ponieważ mój Mac używa Little Endian? Gdybym uruchomił ten sam kod na komputerze typu big endian, czy dałoby to inny wynik? (Otrzymuję ten sam wynik na DartPadzie, ale nie wiem, na jakiej maszynie działa DartPad).

Odpowiedzi

3 ChristopherMoore Dec 20 2020 at 12:03

Tak, można by oczekiwać, że da inny wynik. Otrzymasz oczekiwany wynik w systemie big endian. Twoja obecna metoda przeglądania danych bajtowych wykorzystuje endianness systemu hosta. Obejmuje to DartPad, ponieważ kod działający w DartPad jest kompilowany do JS, który nadal działa w tym samym systemie little endian.

Nie ma określonego endianness dla języka Dart. Jednak niektóre metody przeglądania danych bajtowych jawnie ustawiają endianness, podobnie jak ByteDataklasa.

1 Suragch Dec 28 2020 at 07:10

Oto dodatkowe informacje dotyczące odpowiedzi Christophera Moore'a.

Możesz sprawdzić endianness swojego komputera, wykonując następujące czynności:

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

Większość komputerów osobistych wykorzystuje architekturę little endian, więc ta zwykle powróci true.

Możesz określić endianness, z jakim chcesz przeglądać dane, używając ByteDatazamiast 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'));
}

Wynik to:

0000000100000000 0000000010000000

Jeśli zmieni Endian.bigsię Endian.littlewynik będzie:

0000000000000001 1000000000000000

Możesz przeczytać więcej na ten temat tutaj:

  • Praca z bajtami w Dart