read method

  1. @override
Future<int> read(
  1. List<int> cbuf, [
  2. int offset = 0,
  3. int? length
])
override

Reads characters into an array.

This method will block until some input is available, an I/O error occurs, or the end of the stream is reached.

Parameters

  • cbuf: Destination buffer
  • offset: Offset at which to start storing characters (default: 0)
  • length: Maximum number of characters to read (default: remaining buffer space)

Returns

The number of characters read, or -1 if the end of the stream has been reached.

Example

final reader = FileReader('text.txt');
try {
  final buffer = List<int>.filled(1024, 0);
  final charsRead = await reader.read(buffer);
  if (charsRead != -1) {
    final text = String.fromCharCodes(buffer.sublist(0, charsRead));
    print('Read: $text');
  }
} finally {
  await reader.close();
}

Throws InvalidArgumentException if offset or length is negative, or if offset + length is greater than the length of cbuf. Throws IOException if an I/O error occurs. Throws StreamClosedException if the reader has been closed.

Implementation

@override
Future<int> read(List<int> cbuf, [int offset = 0, int? length]) async {
  checkClosed();

  length ??= cbuf.length - offset;

  if (offset < 0 || length < 0 || offset + length > cbuf.length) {
    throw InvalidArgumentException('Invalid offset or length');
  }

  if (length == 0) {
    return 0;
  }

  int totalRead = 0;

  // First, read from buffer if available
  if (_position < _count) {
    final availableInBuffer = _count - _position;
    final toReadFromBuffer = length.clamp(0, availableInBuffer);

    cbuf.setRange(offset, offset + toReadFromBuffer, _buffer, _position);
    _position += toReadFromBuffer;
    totalRead += toReadFromBuffer;
    offset += toReadFromBuffer;
    length -= toReadFromBuffer;
  }

  // If we need more data and the request is large, read directly
  if (length > 0 && length >= _buffer.length) {
    final directRead = await _reader.read(cbuf, offset, length);
    if (directRead > 0) {
      totalRead += directRead;
    } else if (totalRead == 0) {
      return -1; // End of stream
    }
  } else if (length > 0) {
    // Fill buffer and read from it
    await _fillBuffer();
    if (_count > 0) {
      final toRead = length.clamp(0, _count);
      cbuf.setRange(offset, offset + toRead, _buffer, 0);
      _position = toRead;
      totalRead += toRead;
    } else if (totalRead == 0) {
      return -1; // End of stream
    }
  }

  return totalRead;
}