Is this code an efficient implementation of Reservoir Sampling?
Reviving an old, but really interesting post, that did not get a great opportunity for review the first time around....
What you've done well:
This code, for the most part, is excellent. As for your specific questions:
Is this:

efficient
Mostly, yes. The inefficiencies in here are all related to the IO, and the Scanner, not your code. A more low-level API may net you some performance benefits, but not likely. You are also (re)using the Random class well, and there should not be a problem there.

actually reservoir sampling (with equal odds of any line being drawn)?
Yes. This is a good implementation of the reservoir algorithm. The random arguments are good, and the substitutions should be fine.


What's concerning

The most significant beef is that you do not close the Scanner. Scanners can hold on to open file-handles, and, if the file really is big, this may have system-wide consequences. A try-catch-finally block would be appropriate (or, a try-with-resources if you're on Java7 now).

A second (smaller) issue is that reservoir sampling is designed to handle huge data in a streaming way. I know it is perhaps unrealistic to consider in your use-case, but multi-gigabyte files are not unexpected, and the likelihood of overflowing the count variable is not unrealistic. That would cause problems....

You should consider converting count and randomNumber to be long values, and only convert it back to an int if it is less-than reservoirSize


Finally....
Nice code to review. Thanks. Obviously, the new language features in more recent Java versions may be interesting to consider....