As I remember it the read() level APIs do not do buffering - so if you read() 1 byte at a time you will have a huge perf penalty compared to doing the same thing with fread(). fread() will pull a block and dole it out as you ask for it. read() will drop to the kernel for each call.