Dart TypedData và đại diện endian lớn / nhỏ

Dec 20 2020

Nếu tôi chạy mã sau:

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

Tôi nhận được kết quả sau:

[1, 32768]

Vì các giá trị ban đầu là

00000001 00000000 00000000 10000000
1        0        0        128

Tôi đã mong đợi chúng được kết hợp như thế này:

0000000100000000 0000000010000000
256              128

Thay vào đó, tôi nhận được điều này:

0000000000000001 1000000000000000
1                32768

Đó là một endian nhỏ, phải không? Tôi đang chạy mã này trên máy Mac của mình. Có phải lý do tôi nhận được kết quả ở trên là do máy Mac của tôi sử dụng ít endian không? Nếu tôi chạy cùng một mã trên một máy tính endian lớn, nó có cho kết quả khác không? (Tôi nhận được kết quả tương tự trên DartPad, nhưng tôi không biết DartPad đang chạy trên máy gì.)

Trả lời

3 ChristopherMoore Dec 20 2020 at 12:03

Có, nó sẽ được mong đợi để đưa ra một kết quả khác. Bạn sẽ nhận được kết quả mong đợi của mình trên một hệ thống endian lớn. Phương pháp xem dữ liệu byte hiện tại của bạn sử dụng khả năng kết thúc của hệ thống máy chủ. Điều này bao gồm cả DartPad vì mã chạy trong DartPad đang được biên dịch sang JS, vẫn đang chạy trên cùng một hệ thống endian nhỏ đó.

Không có xác nhận thiết lập cho ngôn ngữ Dart. Tuy nhiên, một số phương pháp xem dữ liệu byte thiết lập rõ ràng một endianness như ByteDatalớp.

1 Suragch Dec 28 2020 at 07:10

Đây là một số thông tin bổ sung cho câu trả lời của Christopher Moore.

Bạn có thể kiểm tra độ bền của máy tính bằng cách sau:

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

Hầu hết các máy tính cá nhân sử dụng ít kiến ​​trúc endian nên thường sẽ quay trở lại true.

Bạn có thể chỉ định độ bền mà bạn muốn xem dữ liệu bằng cách sử dụng ByteDatathay vì 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'));
}

Kết quả là:

0000000100000000 0000000010000000

Nếu bạn thay đổi Endian.bigđể Endian.littlekết quả sẽ là:

0000000000000001 1000000000000000

Bạn có thể đọc thêm về điều này ở đây:

  • Làm việc với byte trong Dart