Stream <list <int>&gt;之间有什么区别?和Dart中的Stream <int> </int> </list <int>

时间:2013-12-21 13:24:55

标签: dart dart-async

我正试图绕着Dart Streams。特别是此example of the command line utility cat具有以下代码行:

 Stream<List<int>> stream = new File(path).openRead();

  // Transform the stream using a `StreamTransformer`. The transformers
  // used here convert the data to UTF8 and split string values into
  // individual lines.
  return stream
      .transform(UTF8.decoder)
      .transform(const LineSplitter())
      .listen((line) {
        if (showLineNumbers) {
          stdout.write('${lineNumber++} ');
        }
        stdout.writeln(line);
      }).asFuture().catchError((_) => _handleError(path));
  1. Stream<T>作为Stream<List<int>>的声明让我感到有些困惑。为什么不将其声明为Stream<int>。 List&lt;&gt;如何?类型使这个不同。订阅者事件是否以某种方式缓冲(如果它是List?

  2. 什么类型(如<T>)传递给第一个转换?是int还是List<int>

  3. 传递给每个下一个变换的类型以及决定其类型的内容。

  4. 此示例是否在将变换结果传递给下一个变换之前读取整个文件?如果是这样,是否有一个示例如何流式传输非常大的文件,类似于此Node问题Parsing huge logfiles in Node.js - read in line-by-line

2 个答案:

答案 0 :(得分:4)

  1. 好问题。
  2. UTF8是一个扩展Codec<String, List<int>>的{​​{3}}。因此Utf8Codec是一个Converter<List<int>, String>,以List<int>为参数。
  3. UTF8.decoderConverter<String, List<String>>。所以它需要String作为参数。生成的.transform(const LineSplitter())流是Stream<String>,其中每行都会被发送。
  4. File.openRead在将第一个字节写入流之前不会读取整个文件。所以处理大文件没问题。

答案 1 :(得分:0)

Alexandre Ardhuin有前三个问题。然而,第四个问题不是。在拆开并删除我自己的代码版本后,我确定了以下内容:

即使在37Mb文件上,转换也只会被调用一次。

这是我用来解决它的代码。

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


void main(List<String> arguments) {

  Stream<List<int>> stream = new File('Data.txt').openRead();

   stream
      .transform(const Utf8InterceptDecoder())
        .transform(const LineSplitterIntercept())
          .listen((line) {
//            stdout.writeln(line);
          }).asFuture().catchError((_) => print(_));
}

int lineSplitCount = 0;

class LineSplitterIntercept extends LineSplitter {

  const LineSplitterIntercept() : super();
  // Never gets called
  List<String> convert(String data) {
    stdout.writeln("LineSplitterIntercept.convert : Data:" + data);
    return super.convert(data);
  }

  StringConversionSink startChunkedConversion(ChunkedConversionSink<String> sink) {
    stdout.writeln("LineSplitterIntercept.startChunkedConversion Count:"+lineSplitCount.toString()+ " Sink: " + sink.toString());
    lineSplitCount++;
    return super.startChunkedConversion(sink);
  }
}

int utfCount = 0;

class Utf8InterceptDecoder extends Utf8Decoder {

  const Utf8InterceptDecoder() : super();

  //never gets called
  String convert(List<int> codeUnits) {
    stdout.writeln("Utf8InterceptDecoder.convert : codeUnits.length:" + codeUnits.length.toString());
    return super.convert(codeUnits);
  }


  ByteConversionSink startChunkedConversion(ChunkedConversionSink<String> sink) {
    stdout.writeln("Utf8InterceptDecoder.startChunkedConversion Count:"+ utfCount.toString() + " Sink: "+ sink.toString());
    utfCount++;
    return super.startChunkedConversion(sink);
  }
}