class DelimitedStreamReader {

  public String read(int numBytes) throws IOException {
    Preconditions.checkArgument(numBytes >= 0);
    Preconditions.checkArgument(numBytes <= MAX_ALLOWABLE_BUFFER_SIZE);
    int numBytesRemaining = numBytes;
    // first read whatever we need from our buffer
    if (!isReadBufferEmpty()) {
      int length = Math.min(end - offset, numBytesRemaining);
      copyToStrBuffer(buffer, offset, length);
      offset += length;
      numBytesRemaining -= length;
    }

    // next read the remaining chars directly into our strBuffer
    if (numBytesRemaining > 0) {
      readAmountToStrBuffer(numBytesRemaining);
    }

    if (strBufferIndex > 0 && strBuffer[strBufferIndex - 1] != LF) {
      // the last byte doesn't correspond to lf
      return readLine(false);
    }

    int strBufferLength = strBufferIndex;
    strBufferIndex = 0;
    return new String(strBuffer, 0, strBufferLength, charset);
  }

}

class DelimitedStreamReaderTest {

  @Test
  public void testMultibyteCharacters() throws Exception {

    String myMessage = "{this is my message: héÿ}\n";
    byte[] bytes = myMessage.getBytes(Charsets.UTF_8);

    InputStream stream = new ByteArrayInputStream(bytes);
    DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);

    // read less bytes than the actual message, but we're lenient so we'll read up to the newline
    String msg = r.read(myMessage.length());
    assertEquals(msg, myMessage);
  }

}