Una buona soluzione è leggere il file dall'inizio fino alla posizione desiderata (risposta di @Chet Simpson). Se si desidera l'ottimizzazione (ad esempio file di grandi dimensioni, posizione da qualche parte nel mezzo, linee tipiche piuttosto brevi), è possibile leggere il file all'indietro. Tuttavia, questo funziona solo con i file aperti in modalità binaria (qualsiasi file su piattaforme unix-like, aprire il file con il parametro ios_base::binary
su Windows).
L'algoritmo è la seguente:
- Torna pochi byte nel file
- Leggere i pochi byte
- Se c'è una linea di fine lì, il resto è facile
- in caso contrario, ripetere
Codice (testato su 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;
}
Edit: Sulle piattaforme Windows-like, in cui end-of-line è caratterizzata da \r\n
, poiché è necessario utilizzare la modalità binaria, stringa di output conterrà il carattere aggiuntivo \r
(a meno che non c'è fine-di- linea alla fine del file), che puoi buttare via.
Cercare l'offset che si ha e quindi andare indietro finché non si trova una nuova riga. Quindi leggi fino alla prossima nuova riga. Facile. –
C'è un modo per leggere un'intera riga in una sola volta, senza leggere da una nuova riga alla successiva? – Meir
Leggere un'intera riga contemporaneamente * è * la lettura da una nuova riga alla successiva. –