首页 > 解决方案 > 如何读取分块流的一部分

问题描述

在 Dart 中,stdin是一个Stream<List<int>>. 字节以块的形式出现。我想要的是一个函数,它从标准输入读取直到我得到一些字符(比如'\0'),然后返回,以便标准输入的未来读者在'\0'.

不幸的是,由于分块,'\0'字节可能位于块的中间,所以我有点想读取一个块,删除其中的一部分,然后将其推回流的开头。但是没有任何方法可以做到这一点。

另一种选择是readByteSync(),但一次读取一个字节会很慢,这是在 GUI 程序中,所以我不能使用同步方法。

标签: dart

解决方案


我认为实际上因为 aStream<>只能被收听一次——即使之前的监听器取消了它的订阅——唯一的方法是让一些东西永久地过滤流的事件,直到时间结束。因此,您不妨将流拆分为两个流:

import 'dart:async';

class StdioPreambleSplitter {
  StdioPreambleSplitter(this._input) {
    var preambleFinished = false;
    _input.listen((chunk) {
      if (preambleFinished) {
        _dataStream.add(chunk);
      } else {
        final nullByte = chunk.indexOf(0);
        if (nullByte == -1) {
          _dataStream.add(chunk);
        } else {
          preambleFinished = true;
          _preambleStream.add(chunk.sublist(0, nullByte));
          _dataStream.add(chunk.sublist(nullByte));
        }
      }
    });
  }

  Stream<List<int>> preambleStream() {
    return _preambleStream.stream;
  }

  Stream<List<int>> dataStream() {
    return _dataStream.stream;
  }

  final Stream<List<int>> _input;
  final StreamController<List<int>> _preambleStream = new StreamController();
  final StreamController<List<int>> _dataStream = new StreamController();
}

希望它不会增加太多开销。


推荐阅读