dart 中不可避免會出現檔案讀取的情況, 甚至是很大的檔案, 比如 200M 的檔案
如果一次性讀入記憶體,雖然也行得通, 但是如果在 flutter 中開啟個 200M 大小的位元組陣列, 一不小心可能就 crash 了, 這時候就需要使用大檔案讀取的方案
讀取檔案
核心方法:
file.openRead();
這個方法可以指定開始和結束的坐標, 并開啟一個 stream
stream 回呼資訊是 List<int>,單次最大讀取 65536 個位元組
示例
class FileUtils {
File file;
FileUtils(this.file);
// 讀取檔案的某個范圍回傳
Future<List<int>> getRange(int start, int end) async {
if (file == null || !file.existsSync()) {
throw FileNotExistsError();
}
if (start < 0) {
throw RangeError.range(start, 0, file.lengthSync());
}
if (end > file.lengthSync()) {
throw RangeError.range(end, 0, file.lengthSync());
}
final c = MyCompleter<List<int>>();
List<int> result = [];
file.openRead(start, end).listen((data) {
result.addAll(data);
}).onDone(() {
c.reply(result);
});
return c.future;
}
}
用到的 completer 在這里
import 'dart:async';
class MyCompleter<T> {
Completer<T> completer = Completer();
MyCompleter();
Future<T> get future => completer.future;
void reply(T result) {
if (!completer.isCompleted) {
completer.complete(result);
}
}
}
這里主要是封裝了一個指定某個范圍回傳的方法, 比如我寫了一個簡單的 dart 包, 通過讀取元資料的方案, 來讀取圖片大小, 這樣不用通過完整的解碼即可完成, 效率比 dart:ui.Image 解碼后查看寬高要高的多
專案地址: https://github.com/CaiJingLong/dart_image_size_getter
比如判斷一個檔案是不是 jpeg 格式, 需要判斷開頭兩個位元組和結尾兩個位元組是不是 0xFF 0xD9 開頭, 0xFF 0xD8 結尾
原始代碼是這樣的, 很不清晰, 也比較難以閱讀:

經過修改后是這樣的
static Future<bool> isJpg(File file) async {
if (file == null || !file.existsSync()) {
return false;
}
const start = [0xFF, 0xD9];
const end = [0xFF, 0xD8];
final completer = MyCompleter<bool>();
void foo() async {
final util = FileUtils(file);
final length = file.lengthSync();
final startList = await util.getRange(0, 2);
final endList = await util.getRange(length - 2, length);
const eq = ListEquality();
completer.reply(eq.equals(start, startList) && eq.equals(end, endList));
}
foo();
return completer.future;
}
后記
專案地址: https://github.com/CaiJingLong/dart_image_size_getter
pub get
dart bin/main.dart
以上
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/1872.html
標籤:Dart
