How to read a file line by line in Dart

dart, dart-io

Solution

The converter's `startChunkedConversion` is only called once, when the transformation is started. However, the returned sink's `add` method is invoked multiple times with parts of the file.

It's up to the source to decide how big the chunks are, but a 37MB file (as mentioned in your previous question) will definitely be sent in smaller chunks.

If you want to see the chunks you can either intercept `startChunkedConversion` and return a wrapped sink, or you can put yourself between the `openRead` and the transformer.

Intercept:

class InterceptSink {
  static int lineSplitCount = 0;

  final _sink;
  InterceptSink(this._sink);
  add(x) {
    print("InterceptSink.add Count: $lineSplitCount");
    lineSplitCount++;
    _sink.add(x);
  }
  close() { _sink.close(); }
}

class LineSplitterIntercept extends Converter {
  convert(x) { throw "unimplemented"; }
  startChunkedConversion(outSink) {
    var lineSink = new LineSplitter().startChunkedConversion(outSink);
    return new InterceptSink(lineSink);
  }
}

After `openRead`:

file.openRead()
  .transform(UTF8.decoder)
  .map(x) {
    print("chunk size: ${x.length)");
    return x;
  }
  .transform(new LineSplitter())
  ...

Problem

This question is a continuation of a previous question. I wrote the following piece of code to determine if `File.openRead()` created a Stream that could be streamed line-by-line. It turns out that the answer is no. The entire file is read and then passed to the next transform. My question is then: How do you Stream a file line-by-line in Dart? ``` 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); } } ```

Original source

Related problems