Dart TypedData и представление с прямым / обратным порядком байтов

Dec 20 2020

Если я запустил следующий код:

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

Получаю такой результат:

[1, 32768]

Поскольку исходные значения были

00000001 00000000 00000000 10000000
1        0        0        128

Я ожидал, что они будут объединены следующим образом:

0000000100000000 0000000010000000
256              128

Вместо этого я получил это:

0000000000000001 1000000000000000
1                32768

Это маленький порядок байтов, правда? Я запускаю этот код на своем Mac. Причина, по которой я получил результат выше, потому что мой Mac использует прямой порядок байтов? Если бы я запустил тот же код на компьютере с прямым порядком байтов, дал бы он другой результат? (Я получаю тот же результат на DartPad, но я не знаю, на какой машине работает DartPad.)

Ответы

3 ChristopherMoore Dec 20 2020 at 12:03

Да, можно было бы ожидать другого результата. Вы получите ожидаемый результат в системе с прямым порядком байтов. Ваш текущий метод просмотра байтовых данных использует порядок байтов хост-системы. Это включает в себя DartPad, поскольку код, работающий в DartPad, компилируется в JS, который по-прежнему работает в той же системе с прямым порядком байтов.

Для языка Dart нет установленного порядка следования байтов. Однако некоторые методы просмотра байтовых данных явно устанавливают порядок байтов, как и ByteDataкласс.

1 Suragch Dec 28 2020 at 07:10

Вот некоторая дополнительная информация к ответу Кристофера Мура.

Вы можете проверить порядок байтов на вашем компьютере с помощью следующего:

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

Большинство персональных компьютеров используют архитектуру с прямым порядком байтов, так что она обычно возвращается true.

Вы можете указать порядок байтов, с которым вы хотите просматривать данные, используя ByteDataвместо 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'));
}

Результат:

0000000100000000 0000000010000000

При изменении Endian.bigв Endian.littleрезультате будет:

0000000000000001 1000000000000000

Подробнее об этом можно прочитать здесь:

  • Работа с байтами в Dart