簡介
檔案操作是IO中非常常見的一種操作,那麼對應dart語言來說,操作檔案是不是很簡單呢?實際上dart提供了兩種讀取檔案的方式,一種是一次性全部讀取,一種是將檔案讀取為流。
一次性讀取的缺點是需要將檔案內容一次性全部載入到記憶體中,如果遇到檔案比較大的情況,就會比較尷尬。所以還需要流式讀取檔案的方式。一起來看看dart中這兩種檔案的讀取方式吧。
File
事實上dart中有很多地方都有File這個類,這裡我們要講解的File類是dart:io包中的。
讀取整個檔案
File代表一個整體的檔案,他有三個建構函式,分別是:
factory File(String path)
factory File.fromUri(Uri uri)
factory File.fromRawPath(Uint8List rawPath)
其中最常用的就是第一個建構函式。
我們可以這樣來構造一個檔案:
var file = File('file.txt');
有了檔案之後,就可以呼叫File中的各種讀取方法。
檔案讀取本身有兩種形式,一種是文字,一種是二進位制。
如果是文字檔案,File提供了readAsString的方法,將整個檔案讀取為字串。
Future<String> readAsString({Encoding encoding: utf8});
我們可以這樣使用:
var stringContents = await file.readAsString();
另外,我們還可以一行一行的對檔案進行讀取:
Future<List<String>> readAsLines({Encoding encoding: utf8});
結果返回的是一個List,list中表示檔案每行的內容。
var lines = await file.readAsLines();
上面兩個方法是非同步的方法,File還提供了兩個同步的方法:
String readAsStringSync({Encoding encoding: utf8});
List<String> readAsLinesSync({Encoding encoding: utf8});
如果檔案是二進位制,那麼可以使用readAsBytes或者同步的方法readAsBytesSync:
Future<Uint8List> readAsBytes();
Uint8List readAsBytesSync();
dart中表示二進位制有一個專門的型別叫做Uint8List,他實際上表示的是一個int的List。
還是剛剛的檔案,我們看下怎麼以二進位制的形式進行讀取:
var file = File('file.txt');
var contents = await file.readAsBytes();
以流的形式讀取檔案
上面我們講到的讀取方式,都是一次性讀取整個檔案,缺點就是如果檔案太大的話,可能造成記憶體空間的壓力。
所以File為我們提供了另外一種讀取檔案的方法,流的形式來讀取檔案.
相應的定義方法如下:
Stream<List<int>> openRead([int? start, int? end]);
我們看一個基本的使用:
import 'dart:io';
import 'dart:convert';
Future<void> main() async {
var file = File('file.txt');
Stream<List<int>> inputStream = file.openRead();
var lines = utf8.decoder
.bind(inputStream)
.transform(const LineSplitter());
try {
await for (final line in lines) {
print('Got ${line.length} characters from stream');
}
print('file is now closed');
} catch (e) {
print(e);
}
}
隨機訪問
一般情況下檔案是順序訪問的,但是有時候我們需要跳過某些前面的資料,直接跳轉到目標地址,則需要對檔案進行隨機訪問。
dart提供了open和openSync兩個方法來進行隨機檔案讀寫:
Future<RandomAccessFile> open({FileMode mode: FileMode.read});
RandomAccessFile openSync({FileMode mode: FileMode.read});
RandomAccessFile提供了對檔案的隨機讀寫方法。非常好用。
檔案的寫入
寫入和檔案讀取一樣,可以一次性寫入或者獲得一個寫入控制程式碼,然後再寫入。
一次性寫入的方法有四種,分別對應字串和二進位制:
Future<File> writeAsBytes(List<int> bytes,
{FileMode mode: FileMode.write, bool flush: false});
void writeAsBytesSync(List<int> bytes,
{FileMode mode: FileMode.write, bool flush: false});
Future<File> writeAsString(String contents,
{FileMode mode: FileMode.write,
Encoding encoding: utf8,
bool flush: false});
void writeAsStringSync(String contents,
{FileMode mode: FileMode.write,
Encoding encoding: utf8,
bool flush: false});
控制程式碼形式可以呼叫openWrite方法,返回一個IOSink物件,然後通過這個物件進行寫入:
IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8});
var logFile = File('log.txt');
var sink = logFile.openWrite();
sink.write('FILE ACCESSED ${DateTime.now()}\n');
await sink.flush();
await sink.close();
預設情況下寫入是會覆蓋整個檔案的,但是可以通過下面的方式來更改寫入模式:
var sink = logFile.openWrite(mode: FileMode.append);
處理異常
雖然dart中所有的異常都是執行時異常,但是和java一樣,要想手動處理檔案讀寫中的異常,則可以使用try,catch:
Future<void> main() async {
var config = File('config.txt');
try {
var contents = await config.readAsString();
print(contents);
} catch (e) {
print(e);
}
}
總結
以上就是dart中的檔案操作了。
本文已收錄於 http://www.flydean.com/23-dart-file/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!