C++ Sto usando std::istream
e ostream
come interfaccia polimorfica per l'accesso casuale binario di I/O in C++, ma sembra non ottimale in molti modi:Raccomandazioni per un polimorfico, ricercabile, I/O binario interfaccia
- Le ricerche a 64 bit sono non portatili e soggette a errori a causa di limiti di stream/streamoff; attualmente utilizzando boost/iostreams/positioning.hpp come una soluzione, ma richiede vigilanza
- operazioni mancanti come troncare o estendere un file (ala POSIX
ftruncate
) - incoerenza tra implementazioni concrete; per esempio.
stringstream
ha posizioni get/put indipendenti mentrefilestream
non - Incoerenza tra le implementazioni della piattaforma; per esempio. comportamento di cercare passare il fine di un file o l'utilizzo di
failbit
/badbit
sugli errori - non hanno bisogno di tutte le strutture di formattazione di
stream
o forse anche il buffer distreambuf
streambuf
segnalazione degli errori (vale a dire le eccezioni contro la restituzione di un indicatore di errore) è presumibilmente implementation-dependent in pratica
mi piace l'interfaccia semplificata fornita dal Boost.Iostreams Device concept, ma è disponibile come modelli funzionali piuttosto che una classe polimorfica. (C'è un device
class, ma non è polimorfico ed è solo una classe helper di implementazione non necessariamente utilizzata dalle implementazioni di dispositivo fornite.) Uso principalmente file di grandi dimensioni, ma voglio davvero il polimorfismo così posso facilmente sostituire le implementazioni alternative (es. utilizzare stringstream
anziché fstream
per i test di unità) senza tutta la complessità e l'accoppiamento in fase di compilazione dell'istanza di modello profonda.
Qualcuno ha qualche raccomandazione su un approccio standard a questo? Sembra una situazione comune, quindi non voglio inventare le mie interfacce inutilmente. Ad esempio, qualcosa come java.nio.FileChannel sembra l'ideale.
La mia soluzione migliore finora è mettere uno strato polimorfo sottile sopra i dispositivi Boost.Iostreams. Ad esempio:
class my_istream
{
public:
virtual std::streampos seek(stream_offset off, std::ios_base::seekdir way) = 0;
virtual std::streamsize read(char* s, std::streamsize n) = 0;
virtual void close() = 0;
};
template <class T>
class boost_istream : public my_istream
{
public:
boost_istream(const T& device) : m_device(device)
{
}
virtual std::streampos seek(stream_offset off, std::ios_base::seekdir way)
{
return boost::iostreams::seek(m_device, off, way);
}
virtual std::streamsize read(char* s, std::streamsize n)
{
return boost::iostreams::read(m_device, s, n);
}
virtual void close()
{
boost::iostreams::close(m_device);
}
private:
T m_device;
};
Grazie per il puntatore, mi ero dimenticato di Qt. Non voglio dipendere da esso, ma fornisce una certa prospettiva. –