title: InputStreamReader buffering issue
body: <p>I am reading data from a file that has, unfortunately, two types of character encoding.</p>
  
  <p>There is a header and a body.  The header is always in ASCII and defines the character set that the body is encoded in.</p>
  
  <p>The header is not fixed length and must be run through a parser to determine its content/length.</p>
  
  <p>The file may also be quite large so I need to avoid bring the entire content into memory.</p>
  
  <p>So I started off with a single InputStream.  I wrap it initially with an InputStreamReader with ASCII and decode the header and extract the character set for the body.  All good.</p>
  
  <p>Then I create a new InputStreamReader with the correct character set, drop it over the same InputStream and start trying to read the body.</p>
  
  <p>Unfortunately it appears, javadoc confirms this, that InputStreamReader may choose to read-ahead for effeciency purposes.  So the reading of the header chews some/all of the body.</p>
  
  <p>Does anyone have any suggestions for working round this issue?  Would creating a CharsetDecoder manually and feeding in one byte at a time but a good idea (possibly wrapped in a custom Reader implementation?)</p>
  
  <p>Thanks in advance.</p>
  
  <p>EDIT:  My final solution was to write a InputStreamReader that has no buffering to ensure I can parse the header without chewing part of the body.  Although this is not terribly efficient I wrap the raw InputStream with a BufferedInputStream so it won't be an issue.</p>
  
  <pre><code>// An InputStreamReader that only consumes as many bytes as is necessary
  // It does not do any read-ahead.
  public class InputStreamReaderUnbuffered extends Reader
  {
      private final CharsetDecoder charsetDecoder;
      private final InputStream inputStream;
      private final ByteBuffer byteBuffer = ByteBuffer.allocate( 1 );
  
      public InputStreamReaderUnbuffered( InputStream inputStream, Charset charset )
      {
          this.inputStream = inputStream;
          charsetDecoder = charset.newDecoder();
      }
  
      @Override
      public int read() throws IOException
      {
          boolean middleOfReading = false;
  
          while ( true )
          {
              int b = inputStream.read();
  
              if ( b == -1 )
              {
                  if ( middleOfReading )
                      throw new IOException( "Unexpected end of stream, byte truncated" );
  
                  return -1;
              }
  
              byteBuffer.clear();
              byteBuffer.put( (byte)b );
              byteBuffer.flip();
  
              CharBuffer charBuffer = charsetDecoder.decode( byteBuffer );
  
              // although this is theoretically possible this would violate the unbuffered nature
              // of this class so we throw an exception
              if ( charBuffer.length() &gt; 1 )
                  throw new IOException( "Decoded multiple characters from one byte!" );
  
              if ( charBuffer.length() == 1 )
                  return charBuffer.get();
  
              middleOfReading = true;
          }
      }
  
      public int read( char[] cbuf, int off, int len ) throws IOException
      {
          for ( int i = 0; i &lt; len; i++ )
          {
              int ch = read();
  
              if ( ch == -1 )
                  return i == 0 ? -1 : i;
  
              cbuf[ i ] = (char)ch;
          }
  
          return len;
      }
  
      public void close() throws IOException
      {
          inputStream.close();
      }
  }
  </code></pre>