code: public static StreamSegmentReadResult read(SegmentProperties segmentInfo, long startOffset, int maxReadLength, int readBlockSize, ReadOnlyStorage storage) {
          Exceptions.checkArgument(startOffset >= 0, "startOffset", "startOffset must be a non-negative number.");
          Exceptions.checkArgument(maxReadLength >= 0, "maxReadLength", "maxReadLength must be a non-negative number.");
          Preconditions.checkNotNull(segmentInfo, "segmentInfo");
          Preconditions.checkNotNull(storage, "storage");
          String traceId = String.format("Read[%s]", segmentInfo.getName());
          return new StreamSegmentReadResult(startOffset, maxReadLength, new SegmentReader(segmentInfo, null, readBlockSize, storage), traceId);
      }
docs: Reads a range of bytes from a Segment in Storage.
  
  @param segmentInfo   A SegmentProperties describing the Segment to read.
  @param startOffset   The first offset within the Segment to read from.
  @param maxReadLength The maximum number of bytes to read.
  @param readBlockSize The maximum number of bytes to read at once (the returned StreamSegmentReadResult will be
  broken down into Entries smaller than or equal to this size).
  @param storage       A ReadOnlyStorage to execute the reads against.
  @return A StreamSegmentReadResult that can be used to process the data. This will be made up of ReadResultEntries
  of the following types: Storage, Truncated or EndOfSegment.