我正试图绕着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));
Stream<T>
作为Stream<List<int>>
的声明让我感到有些困惑。为什么不将其声明为Stream<int>
。 List&lt;&gt;如何?类型使这个不同。订阅者事件是否以某种方式缓冲(如果它是List?
什么类型(如<T>
)传递给第一个转换?是int
还是List<int>
?
传递给每个下一个变换的类型以及决定其类型的内容。
此示例是否在将变换结果传递给下一个变换之前读取整个文件?如果是这样,是否有一个示例如何流式传输非常大的文件,类似于此Node问题Parsing huge logfiles in Node.js - read in line-by-line
答案 0 :(得分:4)
UTF8
是一个扩展Codec<String, List<int>>
的{{3}}。因此Utf8Codec是一个Converter<List<int>, String>
,以List<int>
为参数。Converter<String, List<String>>
。所以它需要String
作为参数。生成的.transform(const LineSplitter())
流是Stream<String>
,其中每行都会被发送。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);
}
}