如何在Dart中打开并关注文件(如tail -f)?

时间:2015-01-02 19:42:28

标签: dart dart-io

是否有一种简单的方法可以打开文件并不断读取它而不会在EOF上关闭流?像Unix命令tail -f

只需在API文档中描述EOF之前阅读。但我看不到一种明显/简单的方法来阻止或暂停流以获得更多输入。

一种解决方案是重复重新打开文件,并在检测到文件大小发生变化时继续读取上一个已知长度。

2 个答案:

答案 0 :(得分:1)

像这样的东西

import 'dart:io';

void main(List<String> args ) {
  var file = new File("test.txt");
  print(file.absolute);
  var openFuture = file.open(mode: FileMode.READ);
  openFuture.then((raf) => raf.length().then((len) => raf.setPosition(len)
      .then((raf) => raf.readXxx...
}

您还可以使用Directory.watch获取有关更改的通知,然后重新打开并从上一个已知位置读取。

答案 1 :(得分:1)

(尽管这个问题现在已经有很多年了,但我今天偶然发现了同样的问题,找不到可行的解决方案,因此不得不推出自己的解决方案,并希望与未来几代 Dart 程序员分享我的发现.;-))

dart:io 包与一些流和 async-await 魔法相结合,应该提供实现类似“tail -f”的功能所需的一切:

import 'dart:typed_data';
import 'dart:io';

Stream<List<int>> tail(final File file) async* {
  final randomAccess = await file.open(mode: FileMode.read);
  var pos = await randomAccess.position();
  var len = await randomAccess.length();
  // Increase/decrease buffer size as needed.
  var buf = Uint8List(8192);

  Stream<Uint8List> _read() async* {
    while (pos < len) {
      final bytesRead = await randomAccess.readInto(buf);
      pos += bytesRead;

      yield buf.sublist(0, bytesRead);
    }
  }

  // Step 1: read whole file
  yield* _read();

  // Step 2: wait for modify events and read more bytes from file
  await for (final event in file.watch(events: FileSystemEvent.modify)) {
    if ((event as FileSystemModifyEvent).contentChanged) {
      len = await (randomAccess.length());
      yield* _read();
    }
  }
}

这个函数 (tail) 可以这样使用:

import 'dart:convert';
import 'dart:io';

void main() {
  final file = File('/var/log/messages');
  tail(file).transform(utf8.decoder).transform(LineSplitter()).forEach((line) {
    // Do something with the line that has been read, e.g. print it out...
    print(line);
  });
}