如何在Dart中逐行读取文件 [英] How to read a file line by line in Dart

查看:720
本文介绍了如何在Dart中逐行读取文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题是上一个问题的延续。我编写了以下代码,以确定 File.openRead()是否创建了可以逐行流式传输的Stream。事实证明答案是否定的。读取整个文件,然后将其传递到下一个转换。我的问题是:如何在Dart中逐行传输文件?

 导入'dart:async'; 
导入 dart:convert;
导入 dart:io;


void main(List< String>参数){

Stream< List< int>流=新文件('Data.txt')。openRead();


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

int lineSplitCount = 0;

类LineSplitterIntercept扩展LineSplitter {

const LineSplitterIntercept():super();
//永远不会被调用
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;

类Utf8InterceptDecoder扩展了Utf8Decoder {

const Utf8InterceptDecoder():super();

//永远不会被调用
字符串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.toString());
utfCount ++;
return super.startChunkedConversion(sink);
}
}


解决方案

转换开始时,转换器的 startChunkedConversion 仅被调用一次。但是,返回的接收器的 add 方法被部分文件多次调用。



这取决于源代码决定块的大小,但是肯定会以较小的块发送37MB的文件(如上一个问题所述)。



如果要查看块您可以拦截 startChunkedConversion 并返回一个包装好的接收器,也可以将自己置于 openRead 和转换器之间。 / p>

拦截:

  class InterceptSink { 
static int lineSplitCount = 0;

最终水槽;
InterceptSink(this._sink);
add(x){
print( InterceptSink.add Count:$ lineSplitCount);
lineSplitCount ++;
_sink.add(x);
}
close(){_sink.close(); }
}

类LineSplitterIntercept扩展了Converter {
convert(x){抛出未实现; }
startChunkedConversion(outSink){
var lineSink = new LineSplitter()。startChunkedConversion(outSink);
返回新的InterceptSink(lineSink);
}
}

openRead之后

  file.openRead()
.transform(UTF8。解码器)
.map(x){
print( chunk size:$ {x.length));
返回x;
}
.transform(new LineSplitter())
...


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

解决方案

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())
  ...

这篇关于如何在Dart中逐行读取文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆