Provides "classical" facilities, based on the model of
		stream-based I/O. This model has some advantages when
		it comes to flexibility and reusability: for example, we can write a method that
		reads data from any type of stream. To read data from a file, we can then pass
		that method a FileInputStream. But equally, we could pass it a
		ByteArrayInputStream to read cached data from memory. 	
		While flexible, this model of I/O puts a lot of onus on the developer to handle lower-level issues such as buffering and
    error checking. It is a relatively verbose API: e.g. to read the contents of a file, we are forced to deal
    "manually" with the mechanics of creating a file input stream with relevant buffering, checking appropriately
    for error conditions and closing the file when finished. 
	The classical Java I/O API is not suitable for certain high-performance I/O as it requires all data
	to be copied from kernal space into user space. 
     |