How do I list the contents of a directory with Dart?

一世执手 提交于 2019-12-03 23:30:58
Nico

The API has changed and I have updated the async code for M4 release (0.5.16_r23799 ):

Future<List<FileSystemEntity>> dirContents(Directory dir) {
  var files = <FileSystemEntity>[];
  var completer = new Completer();
  var lister = dir.list(recursive: false);
  lister.listen ( 
      (file) => files.add(file),
      // should also register onError
      onDone:   () => completer.complete(files)
      );
  return completer.future;
}

This answer is out of date. Please see the accepted answer.

There are two ways to list the contents of a directory using the Dart VM and the dart:io library.

(note: the following only works in the Dart VM when running on the command-line or as a server-side app. This does not work in a browser or when compiled to JavaScript.)

Setup

First, you need to import the dart:io library. This library contains the classes required to access files, directories, and more.

import 'dart:io';

Second, create a new instance of the Directory class.

var dir = new Directory('path/to/my/dir');

Listing contents in a script

The easiest way is to use the new listSync method. This returns a List of contents. By default this does not recurse.

List contents = dir.listSync();
for (var fileOrDir in contents) {
  if (fileOrDir is File) {
    print(fileOrDir.name);
  } else if (fileOrDir is Directory) {
    print(fileOrDir.path);
  }
}

If you want to recurse through directories, you can use the optional parameter recursive.

List allContents = dir.listSync(recursive: true);

WARNING if your directory structure has circular symlinks, the above code will crash because it's following symlinks recursively.

This method, using listSync, is especially useful when you are writing a shell script, command-line utility, or similar app or script with Dart.

Listing contents in a server

A second way to list the contents of a directory is to use the async version of list. You would use this second method when you need to list a directory in response to, say, an HTTP request. Remember that each of Dart's isolates runs in a single thread. Any long running process can block the event loop. When interactivity is important, or serving lots of clients from a single Dart script, use the async version.

With the async version, dir.list() returns a DirectoryLister. You can register three different callbacks on DirectoryLister:

  • onFile: called when a file or directory is encountered
  • onDone: called when the directory lister is done listing contents
  • onError: called when the lister encounters some error

Here is a simple function that returns a Future of a list of strings, containing file names in a directory:

Future<List<String>> dirContents(Directory dir) {
  var filenames = <String>[];
  var completer = new Completer();
  var lister = dir.list();
  lister.onFile = (filename) => filenames.add(filename);
  // should also register onError
  lister.onDone = (_) => completer.complete(filenames);
  return completer.future;
}

Of course, this method is perfect for servers, it's more cumbersome for simple scripts.

Luckily, Dart supports both methods for you to use!

Here is my version using async/await, returning a List of Files only:

List<File> filesInDirectory(Directory dir) async {
  List<File> files = <File>[];
  await for (FileSystemEntity entity in dir.list(recursive: false, followLinks: false)) {
    FileSystemEntityType type = await FileSystemEntity.type(entity.path);
    if (type == FileSystemEntityType.FILE) {
      files.add(entity);
      print(entity.path);
    }
  }
  return files;
}
Ramses Aldama

With this function you can print all the directories and files of a directory. You just need to pass a specific path.

Future listDir(String folderPath) async {
  var directory = new Directory(folderPath);
  print(directory);

  var exists = await directory.exists();
  if (exists) {
    print("exits");

    directory
      .list(recursive: true, followLinks: false)
      .listen((FileSystemEntity entity) {
        print(entity.path);
      });
  }
}

The list method returns a Stream where each emitted event is a directory entry:

Directory dir = Directory('.');
// execute an action on each entry
dir.list(recursive: false).forEach((f) {
  print(f);
});

As the name suggest, listSync method is the blocking version:

// create a list of entries
List<FileSystemEntity> entries = dir.listSync(recursive: false).toList();

What method to use depends on application context. A note directly from the docs:

Unless you have a specific reason for using the synchronous version of a method, prefer the asynchronous version to avoid blocking your program.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!