readLinesReverse function

Stream<String> readLinesReverse(
  1. String path
)

Async generator that yields lines from a file in reverse order. Reads the file backwards in chunks to avoid loading the entire file into memory.

Implementation

Stream<String> readLinesReverse(String path) async* {
  const chunkSize = 1024 * 4;
  final raf = await File(path).open(mode: FileMode.read);
  try {
    final size = await raf.length();
    int position = size;
    List<int> remainder = [];
    final buffer = Uint8List(chunkSize);

    while (position > 0) {
      final currentChunkSize = min(chunkSize, position);
      position -= currentChunkSize;

      await raf.setPosition(position);
      final readCount = await raf.readInto(buffer, 0, currentChunkSize);

      final combined = <int>[...buffer.sublist(0, readCount), ...remainder];

      final newlineChar = '\n'.codeUnitAt(0);
      final firstNewline = combined.indexOf(newlineChar);
      if (firstNewline == -1) {
        remainder = combined;
        continue;
      }

      remainder = combined.sublist(0, firstNewline);
      final text = String.fromCharCodes(combined, firstNewline + 1);
      final lines = text.split('\n');

      for (int i = lines.length - 1; i >= 0; i--) {
        final line = lines[i];
        if (line.isNotEmpty) {
          yield line;
        }
      }
    }

    if (remainder.isNotEmpty) {
      yield String.fromCharCodes(remainder);
    }
  } finally {
    await raf.close();
  }
}