dart 中不可避免會出現文件讀取的狀況, 甚至是很大的文件, 好比 200M 的文件git
若是一次性讀入內存,雖然也行得通, 可是若是在 flutter 中開啓個 200M 大小的字節數組, 一不當心可能就 crash 了, 這時候就須要使用大文件讀取的方案github
核心方法:數組
file.openRead();
這個方法能夠指定開始和結束的座標, 並開啓一個 stream
bash
stream
回調信息是 List<int>
,單次最大讀取 65536
個字節async
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
在這裏ui
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 解碼後查看寬高要高的多this
項目地址: https://github.com/CaiJingLong/dart_image_size_gettercode
好比判斷一個文件是否是 jpeg 格式, 須要判斷開頭兩個字節和結尾兩個字節是否是 0xFF 0xD9 開頭, 0xFF 0xD8 結尾blog
原始代碼是這樣的, 很不清晰, 也比較難以閱讀:
圖片
通過修改後是這樣的
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
以上