The BufferedReader has convert the bytes into chars. This byte by byte parsing and copy to a larger type is expensive relative to a straight copy of blocks of data.
byte[] bytes = new byte[150 * 1024 * 1024];
Arrays.fill(bytes, (byte) '\n');
for (int i = 0; i < 10; i++) {
long start = System.nanoTime();
StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes));
long time = System.nanoTime() - start;
System.out.printf("Time to decode %,d MB was %,d ms%n",
bytes.length / 1024 / 1024, time / 1000000);
}
prints
Time to decode 150 MB was 226 ms
Time to decode 150 MB was 167 ms
NOTE: Having to do this intermixed with system calls can slow down both operations (as system calls can disturb the cache)