如何在Dart文件中写一个`ByteData`实例?

Ren*_*ato 10 dart

我正在使用Flutter将"资产"加载到File一个本地应用程序可以访问它.

这是我加载资产的方式:

final dbBytes = await rootBundle.load('assets/file');
Run Code Online (Sandbox Code Playgroud)

这将返回一个实例ByteData.

如何将其写入dart.io.File实例?

mat*_*rey 18

ByteData 是一个抽象:

固定长度的随机访问字节序列,它还提供对固定宽度整数的随机和非对齐访问以及由这些字节表示的浮点数.

正如Gunter在评论中提到的,你可以使用File.writeAsBytes.这确实需要一些API的工作从得到ByteDataList<int>,但是.

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));
}
Run Code Online (Sandbox Code Playgroud)

我还提出了一个问题,使Flutter上的文档对于这个用例更加明确.

  • 啊,酷。我最终做了 `destinationFile.writeAsBytes(dbBytes.buffer.asUint8List());` (在调试器中,我看到 `dbBytes` 包含一个 `Uint8List`)。我想这和你建议的一样,或者一个比另一个更有效? (2认同)
  • @matanlurey 你给出什么作为路径? (2认同)

Ram*_*him 14

你需要安装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));
}
//======================
Run Code Online (Sandbox Code Playgroud)

获取您的文件:

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

希望这有帮助,谢谢。


cri*_*fan 8

搜索flutter ByteData to List<int>然后找到here,但没有完全回答我的问题:

如何转换ByteDataList<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>();
Run Code Online (Sandbox Code Playgroud)

或 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();
Run Code Online (Sandbox Code Playgroud)

  • Uint8List 是一个 List&lt;int&gt;:抽象类 Uint8List 实现 List&lt;int&gt; (2认同)

Ant*_*REL 7

对于那些希望写入字节(又名 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";
}
Run Code Online (Sandbox Code Playgroud)

如果您使用后一种类型,您可以使用 Rami 提供的答案并修改返回值,如下所示:

@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";
}
Run Code Online (Sandbox Code Playgroud)