@Override
 public synchronized void printStats(final PrintStream out) {
   messageChunkWriter.printStats(out);
   out.println(
       "Number of bits/base "
           + (messageChunkWriter.getTotalBytesWritten() * 8.0f) / (float) sequenceBasesWritten);
 }
 @Override
 public synchronized void appendEntry(final Reads.ReadEntry.Builder entryBuilder)
     throws IOException {
   collectionBuilder.addReads(entryBuilder.build());
   messageChunkWriter.writeAsNeeded(collectionBuilder);
   barcodeIndex = -1;
 }
 public ReadsWriterImpl(final OutputStream output) {
   collectionBuilder = Reads.ReadCollection.newBuilder();
   messageChunkWriter = new MessageChunksWriter(output);
   messageChunkWriter.setParser(new ReadProtobuffCollectionHandler());
   readIndex = 0;
 }
 @Override
 public void setNumEntriesPerChunk(final int numEntriesPerChunk) {
   messageChunkWriter.setNumEntriesPerChunk(numEntriesPerChunk);
 }
  /**
   * Append an entry with a specific read index.
   *
   * @param readIndex Index of the read that will be written
   * @throws IOException If an error occurs while writing the file.
   */
  @Override
  public synchronized void appendEntry(final int readIndex) throws IOException {

    Reads.ReadEntry.Builder entryBuilder = Reads.ReadEntry.newBuilder();

    entryBuilder.setReadIndex(readIndex);

    // set current read index to enable interleaving calls to appendEntry(readIndex)/appendEntry().
    this.readIndex = readIndex;
    if (barcodeIndex != -1) {
      entryBuilder.setBarcodeIndex(barcodeIndex);
    }
    if (description != null) {
      entryBuilder.setDescription(description.toString());
      description = null;
    }
    if (identifier != null) {
      entryBuilder.setReadIdentifier(identifier.toString());
      identifier = null;
    }
    if (sequence != null) {
      entryBuilder.setSequence(encodeSequence(sequence));
      sequence = null;
    }
    entryBuilder.setReadLength(previousReadLength);
    if (pairSequence != null) {
      entryBuilder.setSequencePair(encodeSequence(pairSequence));
      pairSequence = null;
      entryBuilder.setReadLengthPair(previousReadLength);
    }

    if (qualityScores != null) {
      entryBuilder.setQualityScores(ByteString.copyFrom(qualityScores));
      qualityScores = null;
    }

    if (qualityScoresPair != null) {
      entryBuilder.setQualityScoresPair(ByteString.copyFrom(qualityScoresPair));
      qualityScoresPair = null;
    }

    if (firstRead == true && keyValuePairs != null) {
      // Append meta data on the very first read of each file. This is used instead of a separate
      // header file.
      for (Object keyObject : keyValuePairs.keySet()) {
        String key = keyObject.toString();
        String value = keyValuePairs.get(key).toString();
        entryBuilder.addMetaData(Reads.MetaData.newBuilder().setKey(key).setValue(value));
      }
      firstRead = false;
    }
    if (codec != null) {
      if (collectionBuilder.getReadsCount() == 0) {
        codec.newChunk();
      }
      Reads.ReadEntry.Builder result = codec.encode(entryBuilder);
      if (result != null) {
        entryBuilder = result;
      }
    }
    collectionBuilder.addReads(entryBuilder.build());

    messageChunkWriter.writeAsNeeded(collectionBuilder);
    barcodeIndex = -1;
  }
 /** {@inheritDoc} */
 @Override
 public void close() throws IOException {
   messageChunkWriter.close(collectionBuilder);
 }