首页 > 解决方案 > 当我在从文件中读取文本中使用转换时,飞镖附加到文件

问题描述

在这个简单的代码中,我可以显示ids完成读取文件并id从文本文件中获取的所有内容,但是我想将获取的内容附加idJsonObjectTransformer类中,而不是完成读取文件

Future<void> main() async {
  final ids = await File('sample.json')
      .openRead()
      .transform(const Utf8Decoder())
      .transform<dynamic>(JsonObjectTransformer())
      .map((dynamic json) => json['id'] as String)
      .toList();

  print(ids); // [@123456, @123456]
}

class JsonObjectTransformer extends StreamTransformerBase<String, dynamic> {
  static final _openingBracketChar = '{'.codeUnitAt(0);
  static final _closingBracketChar = '}'.codeUnitAt(0);

  @override
  Stream<dynamic> bind(Stream<String> stream) async* {
    final sb = StringBuffer();
    var bracketsCount = 0;

    await for (final string in stream) {
      for (var i = 0; i < string.length; i++) {
        final current = string.codeUnitAt(i);
        sb.writeCharCode(current);

        if (current == _openingBracketChar) {
          bracketsCount++;
        }

        if (current == _closingBracketChar && --bracketsCount == 0) {
          yield json.decode(sb.toString());
          sb.clear();
        }
      }
    }
    
    /*for example this line*/
    //new File('test.txt').writeAsStringSync(sb.toString(), mode: FileMode.APPEND);
  }
}

我怎样才能做到这一点?

标签: dart

解决方案


有多种方法可以做到这一点,但一种简单的方法是更改JsonObjectTransformer​​如下:

class JsonObjectTransformer extends StreamTransformerBase<String, dynamic> {
  static final _openingBracketChar = '{'.codeUnitAt(0);
  static final _closingBracketChar = '}'.codeUnitAt(0);

  @override
  Stream<dynamic> bind(Stream<String> stream) async* {
    final sb = StringBuffer();
    var bracketsCount = 0;
    final ioSink = File('test.txt').openWrite(mode: FileMode.append);

    await for (final string in stream) {
      for (var i = 0; i < string.length; i++) {
        final current = string.codeUnitAt(i);
        sb.writeCharCode(current);

        if (current == _openingBracketChar) {
          bracketsCount++;
        }

        if (current == _closingBracketChar && --bracketsCount == 0) {
          final dynamic jsonObject = json.decode(sb.toString());

          ioSink.writeln(jsonObject['id'] as String);
          yield jsonObject;
          sb.clear();
        }
      }
    }
    
    await ioSink.flush();
    await ioSink.close();
  }
}

一个更干净的解决方案(因为我们需要一些单独的关注点)是Stream在解析每个对象时使用 main 中的 ID 来编写 ID。如何做到这一点的一个例子是:

Future<void> main() async {
  final file = File('test.txt').openWrite(mode: FileMode.append);
  final ids = <String>[];

  await File('sample.json')
      .openRead()
      .transform(const Utf8Decoder())
      .transform<dynamic>(JsonObjectTransformer())
      .map((dynamic json) => json['id'] as String)
      .forEach((id) {
    file.writeln(id);
    ids.add(id);
  });

  await file.flush();
  await file.close();

  print(ids); // [@123456, @123456]
}

推荐阅读