dart series: smooth as silk, operating files and directories

Posted by Dj Kat on Wed, 22 Dec 2021 17:23:41 +0100

brief introduction

File operation is a very common operation in IO. Is it easy to operate files in dart language? In fact, dart provides two ways to read files, one is to read all files at once, and the other is to read files as streams.

The disadvantage of one-time reading is that you need to load all the file contents into memory at one time. If you encounter a large file, it will be embarrassing. Therefore, we also need the way of streaming reading files. Let's take a look at the reading methods of these two files in dart.

File

In fact, there are many places in dart that have the File class. The File class we want to explain here is in the dart:io package.

Read entire file

File represents a whole file. It has three constructors:

factory File(String path) 

factory File.fromUri(Uri uri)

factory File.fromRawPath(Uint8List rawPath)

One of the most commonly used is the first constructor.

We can construct a file like this:

var file = File('file.txt');

Once you have the File, you can call various read methods in the File.

File reading itself has two forms, one is text and the other is binary.

If it is a text File, File provides a readAsString method to read the entire File as a string.

  Future<String> readAsString({Encoding encoding: utf8});

We can use this:

 var stringContents = await file.readAsString();

In addition, we can read the file line by line:

Future<List<String>> readAsLines({Encoding encoding: utf8});

The result is a list, which represents the contents of each line of the file.

 var lines = await file.readAsLines();

The above two methods are asynchronous methods. File also provides two synchronous methods:

String readAsStringSync({Encoding encoding: utf8});

List<String> readAsLinesSync({Encoding encoding: utf8});

If the file is binary, you can use readAsBytes or the synchronous method readAsBytes Sync:

Future<Uint8List> readAsBytes();

Uint8List readAsBytesSync();

dart has a special type called Uint8List, which actually represents an int List.

Let's see how to read the file in binary form:

var file = File('file.txt');
var contents = await file.readAsBytes();

Read file as stream

The reading methods mentioned above are to read the whole file at one time. The disadvantage is that if the file is too large, it may cause pressure on memory space.

Therefore, File provides us with another way to read files in the form of stream

The corresponding definition method is as follows:

  Stream<List<int>> openRead([int? start, int? end]);

Let's look at a basic use:

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);
  }
}

Random access

Generally, files are accessed sequentially, but sometimes we need to skip some previous data and directly jump to the target address, so we need to access the files randomly.

dart provides open and openSync methods to read and write random files:

  Future<RandomAccessFile> open({FileMode mode: FileMode.read});
  RandomAccessFile openSync({FileMode mode: FileMode.read});

RandomAccessFile provides random reading and writing methods for files. Very easy to use.

File writing

Writing is the same as file reading. You can write at one time or obtain a write handle before writing.

There are four write once methods, corresponding to string and binary respectively:

 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});

In the form of handle, you can call the openWrite method, return an IOSink object, and then write through this object:

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();

By default, writing will overwrite the entire file, but you can change the write mode in the following ways:

var sink = logFile.openWrite(mode: FileMode.append);

Handling exceptions

Although all exceptions in dart are runtime exceptions, like java, you can use try,catch:

Future<void> main() async {
  var config = File('config.txt');
  try {
    var contents = await config.readAsString();
    print(contents);
  } catch (e) {
    print(e);
  }
}

summary

The above is the file operation in dart.

This article has been included in http://www.flydean.com/23-dart-file/

The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to find!

Welcome to my official account: "those things in procedure", understand technology, know you better!

Topics: Java dart