2012-01-22 19 views
6

¿Puedo abrir un ifstream (o configurar uno existente de alguna manera) para que solo lea parte de un archivo? Por ejemplo, me gustaría que mi ifstream lea un archivo del byte 10 al 50. Buscar en el puesto 0 sería la posición 10 en realidad, leer la posición anterior 40 (50 en realidad) sería resualt en un EOF, etc. ¿Es esto posible? ¿de cualquier manera?leer parte de un archivo con iostreams

Respuesta

7

Definitivamente se puede hacer implementando un buffer de flujo de filtrado: obtendrá de std::streambuf y tomará el rango que desea exponer y el buffer de flujo subyacente (bueno, un puntero) como argumentos. Entonces buscarías la ubicación de inicio. Una función underflow() reemplazada leería desde el almacenamiento intermedio de flujo subyacente en su memoria intermedia hasta que haya consumido tantos caracteres como se deseaba. Aquí es una versión algo áspero y no probado por completo:

#include <streambuf> 
struct rangebuf: std::streambuf { 
    rangebuf(std::streampos start, 
        size_t size, 
        std::streambuf* sbuf): 
     size_(size), sbuf_(sbuf) 
    { 
     sbuf->seekpos(start, std::ios_base::in); 
    } 
    int underflow() { 
     size_t r(this->sbuf_->sgetn(this->buf_, 
      std::min<size_t>(sizeof(this->buf_), this->size_)); 
     this->size -= r; 
     this->setg(this->buf_, this->buf_, this->buf_ + r); 
     return this->gptr() == this->egptr() 
      ? traits_type::eof() 
      : traits_type::to_int_type(*this->gptr()); 
    } 
    size_t size_; 
    std::streambuf* sbuf_; 
}; 

Se puede utilizar un puntero a una instancia de este búfer de la secuencia de initialuze un std::istream. Si es una necesidad recurrente, puede crear una clase derivada de std::istream configurando el búfer de secuencia en su lugar.

4

Puede leer los bytes que desea en una cadena o matriz char, luego puede usar esa cadena con una cadena istringstream, y usar eso en lugar de su ifstream. Ejemplo:

std::ifstream fin("foo.txt"); 
fin.seekg(10); 
char buffer[41]; 
fin.read(buffer, 40); 
buffer[40] = 0; 
std::istringstream iss(buffer); 
for (std::string s; iss >> s;) std::cout << s << '\n'; 

Si tiene que manejar archivos binarios, se puede hacer eso también:

std::ifstream fin("foo.bin", std::ios::binary | std::ios::in); 
fin.seekg(10); 
char buffer[40]; 
fin.read(buffer, 40); 
std::istringstream(std::string(buffer, buffer+40)); 
+0

Cabe señalar que esta solución solo funcionará con archivos de texto. –

+2

@KhaledNassar: Se puede adaptar fácilmente para trabajar con archivos binarios. Hecho. –

+0

Un problema con este enfoque es que el enfoque que debe leerse puede ser bastante grande. Claro que si de verdad es tremendo es posible que desee cuidar el rango por separado de todos modos. –

2

Es posible que desee poner en práctica su propia clase lector corriente (preferiblemente a través de alguna de las interfaces ifstream si es que existe) .

Cuestiones relacionadas