public SortedMap<Integer, String> find(int from, int to, String regex) throws IOException {
    assertIsOpen();
    if (regex == null) {
      throw new NullPointerException("Regex cannot be null");
    }
    if (from < 1) {
      throw new IllegalArgumentException("'from' must be greater than or equal to 1");
    }
    if (to < from) {
      throw new IllegalArgumentException("'to' must be greater than or equal to 'from'");
    }

    SortedMap<Integer, String> lines = new TreeMap<>();
    List<Long> positions = new ArrayList<>(index);

    try {
      lock.lock();

      raf.seek(positions.get(from - 1));
      for (int i = from; i <= to; i++) {
        String line = raf.getNextLine(charset);
        if (line != null) {
          if (line.matches(regex)) {
            lines.put(i, line);
          }
        } else {
          break;
        }
      }

      return lines;
    } finally {
      lock.unlock();
    }
  }
  /**
   * Read from line to line
   *
   * @param from
   * @param to
   * @return
   * @throws IOException
   */
  public SortedMap<Integer, String> readLines(int from, int to) throws IOException {
    assertIsOpen();
    if (from < 1) {
      throw new IllegalArgumentException("'from' must be greater than or equal to 1");
    }
    if (to < from) {
      throw new IllegalArgumentException("'to' must be greater than or equal to 'from'");
    }
    if (from > index.size()) {
      throw new IllegalArgumentException("'from' must be less than the file's number of lines");
    }

    SortedMap<Integer, String> lines = new TreeMap<>();
    List<Long> positions = new ArrayList<>(index);

    try {
      lock.lock();

      raf.seek(positions.get(from - 1));
      for (int i = from; i <= to; i++) {
        String line = raf.getNextLine(charset);
        if (line != null) {
          lines.put(i, line);
        } else {
          break;
        }
      }

      return lines;
    } finally {
      lock.unlock();
    }
  }
    @Override
    protected SortedSet<Long> compute() {
      SortedSet<Long> index = new TreeSet<>();
      try {
        if (length < threshold) {
          BufferedAccessFile raf = null;
          try {
            raf = new BufferedAccessFile(file, "r");
            raf.seek(start);

            // Add the position for 1st line
            if (raf.getFilePointer() == 0L) {
              index.add(raf.getFilePointer());
            }
            while (raf.getFilePointer() < end) {
              raf.getNextLine();
              index.add(raf.getFilePointer());
            }
          } finally {
            if (raf != null) {
              raf.close();
            }
          }
        } else {
          long start1 = start;
          long end1 = start + (length / 2);

          long end2 = end;

          IndexingTask task1 = new IndexingTask(file, start1, end1, threshold);
          task1.fork();
          IndexingTask task2 = new IndexingTask(file, end1, end2, threshold);

          index.addAll(task2.compute());
          index.addAll(task1.join());
        }
      } catch (IOException ex) {
        throw new FileReaderException("Error while index file:" + ex.getMessage(), ex);
      }

      return index;
    }
 @Override
 public void close() throws IOException {
   raf.close();
   isClosed = true;
 }