@Override
 public void writeBytes(byte[] b, int offset, int length) throws IOException {
   int bytesLeft = bufferSize - bufferPosition;
   // is there enough space in the buffer?
   if (bytesLeft >= length) {
     // we add the data to the end of the buffer
     System.arraycopy(b, offset, buffer, bufferPosition, length);
     bufferPosition += length;
     // if the buffer is full, flush it
     if (bufferSize - bufferPosition == 0) flush();
   } else {
     // is data larger then buffer?
     if (length > bufferSize) {
       // we flush the buffer
       if (bufferPosition > 0) flush();
       // and write data at once
       crc.update(b, offset, length);
       flushBuffer(b, offset, length);
       bufferStart += length;
     } else {
       // we fill/flush the buffer (until the input is written)
       int pos = 0; // position in the input data
       int pieceLength;
       while (pos < length) {
         pieceLength = (length - pos < bytesLeft) ? length - pos : bytesLeft;
         System.arraycopy(b, pos + offset, buffer, bufferPosition, pieceLength);
         pos += pieceLength;
         bufferPosition += pieceLength;
         // if the buffer is full, flush it
         bytesLeft = bufferSize - bufferPosition;
         if (bytesLeft == 0) {
           flush();
           bytesLeft = bufferSize;
         }
       }
     }
   }
 }
 @Override
 public long getChecksum() throws IOException {
   flush();
   return crc.getValue();
 }
 @Override
 public void writeByte(byte b) throws IOException {
   if (bufferPosition >= bufferSize) flush();
   buffer[bufferPosition++] = b;
 }
 @Override
 public void close() throws IOException {
   flush();
 }