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