Well I guess you could see the method that takes a file as an automatic optimisation in that it will be a lot quicker to just pattern match the file extension rather than try and open every reader, some of which have time-consuming constructors to read metadata etc. In 99.9% of cases this is a perfectly valid assumption that files should have the right extension.
I guess it depends on what stance you take as to what a valid file is. Personally I think that if a file has a .wav extension but actually contains aiff data then the file is invalid and should not return a valid reader for it. You might want to notify the user that the file has the wrong extension or similar. If JUCE did this automatically there would be no way of knowing this peculiarity as all the readers are private, they only expose the base class implementation.
Having said that it is often nice to just go ahead and read the file anyway but in this instance what your saying is that the file is invalid but the stream of data the file refers to is valid. In this case I would just provide an additional method that uses AudioFormatManager::createReaderFor (InputStream* audioFileStream) as a backup. I would say that most applications have some container class for file reading etc. which might deliver other, optimised readers (like MemoryMappedAudioFormatReader) where possible, so you could just modify your reader creator method to something like:
[code]AudioFormatReader* createReader (const File& audioFile)
if (AudioFormatReader* reader = manager.createReaderFor (audioFile))
if (AudioFormatReader* reader = manager.createReaderFor (audioFile.createInputStream()))