code: package zemberek.lm.compression;
  
  
  import java.io.File;
  import java.io.IOException;
  import java.io.RandomAccessFile;
  import java.util.Arrays;
  import java.util.Iterator;
  import zemberek.core.hash.ByteGramProvider;
  import zemberek.core.hash.IntHashKeyProvider;
  
  public class ChunkingNGramReader implements Iterable<IntHashKeyProvider> {
  
    File file;
    int chunkGramSize;
    int chunkByteSize;
    int order;
  
    public ChunkingNGramReader(File file, int order, int chunkGramSize) {
      this.file = file;
      this.order = order;
      this.chunkGramSize = chunkGramSize;
      this.chunkByteSize = chunkGramSize * order * 4;
    }
  
    public Iterator<IntHashKeyProvider> iterator() {
      return new ChunkIterator();
    }
  
    private class ChunkIterator implements Iterator<IntHashKeyProvider> {
  
      RandomAccessFile raf;
      int readByteAmount;
      byte[] data;
  
      private ChunkIterator() {
        data = new byte[chunkByteSize];
        try {
          raf = new RandomAccessFile(file, "r");
          raf.skipBytes(8);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
  
      public boolean hasNext() {
        try {
          readByteAmount = raf.read(data);
          if (readByteAmount > 0) {
            if (readByteAmount < chunkByteSize) {
              data = Arrays.copyOf(data, readByteAmount);
            }
            return true;
          } else {
            raf.close();
            return false;
          }
  
        } catch (IOException e) {
          e.printStackTrace();
        }
        return false;
      }
  
      public IntHashKeyProvider next() {
        return new ByteGramProvider(data, order, readByteAmount / (order * 4));
      }
  
      public void remove() {
        throw new UnsupportedOperationException("Not valid!");
      }
    }
  
  }
  