【问题标题】:How do I open and follow a file in Dart (like tail -f)?如何在 Dart 中打开和关注文件(如 tail -f)?
【发布时间】:2015-01-02 19:42:28
【问题描述】:

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

API 文档中描述了EOF 之前的内容。但我看不到一种明显/简单的方法来阻止或暂停流以获取更多输入。

当我检测到文件大小已更改时,一种解决方案是反复重新打开文件并从最后一个已知长度继续读取。

【问题讨论】:

    标签: dart dart-io


    【解决方案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 来获取有关更改的通知,然后重新打开并从最后一个已知位置读取。

    【讨论】:

      【解决方案2】:

      (尽管这个问题现在已经有很多年了,但我今天偶然发现了同样的问题并且找不到可行的解决方案,因此不得不推出自己的解决方案,并希望与未来几代的 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);
        });
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-10
        • 2014-07-12
        • 2012-07-05
        • 1970-01-01
        • 2013-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多