The first way is better, because of the Liskov Substitution Principle. A base class which offers read and write but actually can't promise that either will work is basically useless. Two base classes which offer guaranteed functionality are much more useful.
On the other hand, proceed with caution, because while it is tempting to think that reading and writing can be abstracted cleanly, it is often not the case. For example, reading and writing using network sockets requires extra state to handle asynchronous operation; reading datagrams from UDP has different semantics than packets from TCP, etc.