Una buena solución es leer el archivo desde el principio hasta la posición deseada (respuesta por @Chet Simpson). Si desea la optimización (por ejemplo, un archivo muy grande, posición en el medio, líneas típicas bastante cortas), puede leer el archivo al revés. Sin embargo, esto solo funciona con archivos abiertos en modo binario (cualquier archivo en plataformas unix; abre el archivo con el parámetro ios_base::binary
en Windows).
El algoritmo es el siguiente:
- Volver unos pocos bytes en el archivo
- Leer los pocos bytes
- Si hay una línea de fin de ahí, el resto es fácil
- en caso contrario, repetir
Código (probado en Windows):
std::string GetSurroundingLine(std::istream& f, std::istream::pos_type start_pos)
{
std::istream::pos_type prev_pos = start_pos;
std::istream::pos_type pos;
char buffer[40]; // typical line length, so typical iteration count is 1
std::istream::pos_type size = sizeof(buffer);
// Look for the beginning of the line that includes the given position
while (true)
{
// Move back 40 bytes from prev_pos
if (prev_pos < size)
pos = 0;
else
pos = prev_pos - size;
f.seekg(pos);
// Read 40 bytes
f.read(buffer, prev_pos - pos);
if (!f)
throw;
// Look for a newline byte, which terminates previous line
int eol_pos;
for (eol_pos = sizeof(buffer) - 1; eol_pos >= 0; --eol_pos)
if (buffer[eol_pos] == '\n')
break;
// If found newline or got to beginning of file - done looking
if (eol_pos >= 0 || pos == (std::istream::pos_type)0)
{
pos += eol_pos + 1;
break;
}
}
// Position the read pointer
f.seekg(pos);
// Read the line
std::string s;
std::getline(f, s, '\n');
return s;
}
Editar: En las plataformas de Windows-como, en los que al final de la línea está marcada por \r\n
, ya que se debe utilizar el modo binario, la cadena de salida contendrá el carácter adicional \r
(a menos que no hay fin-de- línea al final del archivo), que puede tirar.
Busque el desplazamiento que tiene, y luego retroceda hasta encontrar una nueva línea. Luego lea hasta la próxima nueva línea. Fácil. –
¿Hay alguna forma de leer toda una línea a la vez, sin leer de una línea nueva a la siguiente? – Meir
Leer toda una línea a la vez * es * leer de una nueva línea a la siguiente. –