Как записать экземпляр ByteData в файл в Dart?

Я использую Flutter для загрузки «актива» в File, чтобы собственное приложение могло получить к нему доступ.

Вот как я загружаю актив:

final dbBytes = await rootBundle.load('assets/file');

Это возвращает экземпляр ByteData.

Как я могу записать это в экземпляр dart.io.File?

37
0
32 959
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

ByteData - это абстракция для:

A fixed-length, random-access sequence of bytes that also provides random and unaligned access to the fixed-width integers and floating point numbers represented by those bytes.

Как упоминал Гюнтер в комментариях, вы можете использовать File.writeAsBytes. Однако для перехода от ByteData к List<int> требуется немного работы с API.

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

Future<void> writeToFile(ByteData data, String path) {
  final buffer = data.buffer;
  return new File(path).writeAsBytes(
      buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}

У меня также есть подал вопрос, чтобы сделать документацию по Flutter более понятной для этого варианта использования.

Ах, круто. Я закончил тем, что сделал destinationFile.writeAsBytes(dbBytes.buffer.asUint8List()); (в отладчике я увидел, что dbBytes содержит Uint8List). Полагаю, это то же самое, что вы предложили, или один из них эффективнее другого?

Renato 01.05.2018 20:31

Помните, что ByteData может быть представлением части буфера, поэтому вы можете не захотеть записывать весь буфер. Я обновил пример, чтобы учесть это.

lrn 02.05.2018 11:00

По какой-то причине ваш writeToFile не работает для> 665 МБ данных. Вы знаете, нужно ли мне устанавливать gradle.properties или подобное? Или у вас есть другое предложение, как писать большие файлы?

iKK 12.01.2019 15:21

@matanlurey Что вы указываете в качестве пути?

Ant D 23.03.2019 16:01

для поиска flutter ByteData to List<int>, затем нашел здесь, но не полностью ответил на мой вопрос:

как конвертировать ByteData в List<int>?

после самостоятельного исследования решение:

  1. использовать .cast<int>()
ByteData audioByteData = await rootBundle.load(audioAssetsFullPath);
Uint8List audioUint8List = audioByteData.buffer.asUint8List(audioByteData.offsetInBytes, audioByteData.lengthInBytes);
List<int> audioListInt = audioUint8List.cast<int>();

или 2. используйте .map

ByteData audioByteData = await rootBundle.load(audioAssetsFullPath);
Uint8List audioUint8List = audioByteData.buffer.asUint8List(audioByteData.offsetInBytes, audioByteData.lengthInBytes);
List<int> audioListInt = audioUint8List.map((eachUint8) => eachUint8.toInt()).toList();

Uint8List - это List <int>: абстрактный класс Uint8List реализует List <int>

Lukasz Ciastko 20.11.2019 22:50

Спасибо за ваше продуманное решение, но как зашифровать / расшифровать байтовые данные во флаттере

moslem 24.01.2020 10:29

у вас должен быть установлен пакет path_provider, тогда

Это должно работать:

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';

final dbBytes = await rootBundle.load('assets/file'); // <= your ByteData

//=======================
Future<File> writeToFile(ByteData data) async {
    final buffer = data.buffer;
    Directory tempDir = await getTemporaryDirectory();
    String tempPath = tempDir.path;
    var filePath = tempPath + '/file_01.tmp'; // file_01.tmp is dump file, can be anything
    return new File(filePath).writeAsBytes(
        buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
//======================

чтобы получить ваш файл:

var file;
try {
    file = await writeToFile(dbBytes); // <= returns File
} catch(e) {
    // catch errors here
}

Надеюсь это поможет, Спасибо.

Для тех, кто хочет писать байты (также известные как Uint8List) вместо ByteData, обратите внимание, что ByteData - это оболочка для Uint8List.

Из /runtime/lib/typed_data.patch:

@patch
class ByteData implements TypedData {
  @patch
  @pragma("vm:entry-point")
  factory ByteData(int length) {
    final list = new Uint8List(length) as _TypedList;
    _rangeCheck(list.lengthInBytes, 0, length);
    return new _ByteDataView(list, 0, length);
  }

@patch
class Uint8List {
  @patch
  @pragma("vm:exact-result-type", _Uint8List)
  factory Uint8List(int length) native "TypedData_Uint8Array_new";
}

Если вы используете последний тип, вы можете использовать ответ, предоставленный Рами, и изменить возвращаемый результат следующим образом:

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';


Future<File> writeToFile(Uint8List data) async {
    (...)
    return new File(filePath).writeAsBytes(data);
}

Другие вопросы по теме