【问题标题】:What is the difference between Stream<List<int>> and Stream<int> in DartDart 中的 Stream<List<int>> 和 Stream<int> 有什么区别
【发布时间】:2014-01-10 06:02:46
【问题描述】:

我正在尝试围绕 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&lt;T&gt; 声明为Stream&lt;List&lt;int&gt;&gt; 让我有点困惑。为什么不声明为Stream&lt;int&gt;。 List 类型如何使它与众不同。如果是 List,订阅者事件是否以某种方式缓冲?

  2. 什么类型(如&lt;T&gt;)被传递给第一个转换?是int 还是List&lt;int&gt;?

  3. 将什么类型传递给每个下一个转换以及决定它们的类型的因素。

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

  5. 的非常大的文件

【问题讨论】:

    标签: dart dart-async


    【解决方案1】:
    1. 好问题。
    2. UTF8 是一个扩展 Codec&lt;String, List&lt;int&gt;&gt; 的 Utf8Codec。所以UTF8.decoder 是一个Converter&lt;List&lt;int&gt;, String&gt;,它以List&lt;int&gt; 作为参数。
    3. LineSplitter 是 Converter&lt;String, List&lt;String&gt;&gt;。所以它将String 作为参数。 .transform(const LineSplitter()) 的结果流是 Stream&lt;String&gt;,每行都在其中发送。
    4. File.openRead 在将第一个字节写入流之前不会读取整个文件。所以处理大文件没有问题。

    【讨论】:

    • 我还是怀疑解析。我怀疑整个文件都被解析了。我正在构建一个测试,其中包含一些记录内容并调用继承类的拦截转换。
    • 我刚刚用new File('someBigFile').openRead().listen((l){print(l.length);}); 进行了测试,它打印了几个65536。
    【解决方案2】:

    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);
      }
    }
    

    【讨论】:

    • Alexandre Ardhuin 是对的。您正在拦截错误的方法。我回答了你的另一个堆栈溢出问题。
    猜你喜欢
    • 2021-07-22
    • 2021-09-12
    • 2017-02-23
    • 2020-07-02
    • 2010-12-08
    • 2019-10-12
    • 1970-01-01
    • 2020-05-05
    • 2015-11-04
    相关资源
    最近更新 更多