The only thing I can say is that for only sequential reading you can have a lot of memmove that should’nt be there.
I don’t get the use of
while (bytesRead < bufferSize)
buffer [bytesRead++] = 0;
There is no reason to blank the end of the buffer when you’ve done reading the file.
That’s up to the user to take this into account.
In my code I take into account some backtracking as I memmove the data that can be saved.
For sure my implementation is faster for sequential only reading.
For big back tracking, same speed I would say.
small back tracking would need some test, not sure who would be faster.
But maybe indeed only the read modification can be enough
with the remove of the end blanking(no real speed gain but avoid some difference between normal InputStream and buffered one)