Leer archivo línea por línea usando ifstream en C++


El contenido del archivo.txt son:

5 3
6 4
7 1
10 5
11 6
12 3
12 4

Donde 5 3 es un par de coordenadas. ¿Cómo puedo procesar estos datos línea por línea en C++?

Soy capaz de obtener la primera línea, pero ¿cómo puedo obtener la siguiente línea del archivo?

ifstream myfile;
myfile.open ("text.txt");
Author: jww, 2011-10-24

7 answers

Primero, hacer un ifstream:

#include <fstream>
std::ifstream infile("thefile.txt");

Los dos métodos estándar son:

  1. Suponga que cada línea consta de dos números y lea token por token:

    int a, b;
    while (infile >> a >> b)
    {
        // process pair (a,b)
    }
    
  2. Análisis basado en líneas, usando secuencias de cadenas:

    #include <sstream>
    #include <string>
    
    std::string line;
    while (std::getline(infile, line))
    {
        std::istringstream iss(line);
        int a, b;
        if (!(iss >> a >> b)) { break; } // error
    
        // process pair (a,b)
    }
    

No debe mezclar (1) y (2), ya que el análisis basado en tokens no engulle nuevas líneas, por lo que puede terminar con líneas vacías espurias si usa getline() después de que la extracción basada en tokens lo llevó al final de una línea ya.

 709
Author: Kerrek SB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-28 06:57:55

Use ifstream para leer datos de un archivo:

std::ifstream input( "filename.ext" );

Si realmente necesitas leer línea por línea, entonces haz esto:

for( std::string line; getline( input, line ); )
{
    ...for each line in input...
}

Pero probablemente solo necesite extraer pares de coordenadas:

int x, y;
input >> x >> y;

Actualización:

En tu código usas ofstream myfile;, sin embargo el o en ofstream significa output. Si desea leer desde el archivo (entrada) utilice ifstream. Si desea leer y escribir use fstream.

 142
Author: K-ballo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-07 18:04:10

Dado que sus coordenadas pertenecen juntas como pares, ¿por qué no escribir una estructura para ellas?

struct CoordinatePair
{
    int x;
    int y;
};

Entonces puede escribir un operador de extracción sobrecargado para istreams:

std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
    is >> coordinates.x >> coordinates.y;

    return is;
}

Y luego puedes leer un archivo de coordenadas directamente en un vector como este:

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    char filename[] = "coordinates.txt";
    std::vector<CoordinatePair> v;
    std::ifstream ifs(filename);
    if (ifs) {
        std::copy(std::istream_iterator<CoordinatePair>(ifs), 
                std::istream_iterator<CoordinatePair>(),
                std::back_inserter(v));
    }
    else {
        std::cerr << "Couldn't open " << filename << " for reading\n";
    }
    // Now you can work with the contents of v
}
 8
Author: Martin Broadhurst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-20 16:58:07

Ampliando la respuesta aceptada, si la entrada es:

1,NYC
2,ABQ
...

Usted todavía será capaz de aplicar la misma lógica, así:

#include <fstream>

std::ifstream infile("thefile.txt");
if (infile.is_open()) {
    int number;
    std::string str;
    char c;
    while (infile >> number >> c >> str && c == ',')
        std::cout << number << " " << str << "\n";
}
infile.close();
 5
Author: gsamaras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-25 22:18:44

La lectura de un archivo línea por línea en C++ se puede hacer de diferentes maneras.

[Rápido] Bucle con std:: getline ()

El enfoque más simple es abrir un std::ifstream y un bucle usando llamadas std::getline (). El código es limpio y fácil de entender.

#include <fstream>

std::ifstream file(FILENAME);
if (file.is_open()) {
    std::string line;
    while (getline(file, line)) {
        // using printf() in all tests for consistency
        printf("%s", line.c_str());
    }
    file.close();
}

[Rápido] Use file_description_source de Boost

Otra posibilidad es usar la biblioteca Boost, pero el código se vuelve un poco más detallado. El rendimiento es bastante similar al código anterior (Bucle con std:: getline ()).

#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>

namespace io = boost::iostreams;

void readLineByLineBoost() {
    int fdr = open(FILENAME, O_RDONLY);
    if (fdr >= 0) {
        io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
        io::stream <io::file_descriptor_source> in(fdDevice);
        if (fdDevice.is_open()) {
            std::string line;
            while (std::getline(in, line)) {
                // using printf() in all tests for consistency
                printf("%s", line.c_str());
            }
            fdDevice.close();
        }
    }
}

[Más rápido] Utilice el código C

Si el rendimiento es crítico para su software, puede considerar usar el lenguaje C. Este código puede ser 4-5 veces más rápido que las versiones de C++ anteriores, consulte benchmark a continuación

FILE* fp = fopen(FILENAME, "r");
if (fp == NULL)
    exit(EXIT_FAILURE);

char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
    // using printf() in all tests for consistency
    printf("%s", line);
}
fclose(fp);
if (line)
    free(line);

Benchmark Which ¿Cuál es más rápido?

He hecho algunos puntos de referencia de rendimiento con el código anterior y los resultados son interesantes. He probado el código con archivos ASCII que contienen 100.000 líneas, 1.000.000 líneas y 10.000.000 líneas de texto. Cada línea de texto contiene 10 palabras en promedio. El programa se compila con la optimización -O3 y su salida se reenvía a /dev/null para eliminar la variable de tiempo de registro de la medición. Por último, pero no menos importante, cada pieza de código registra cada línea con la función printf() para mayor consistencia.

Los resultados muestran el tiempo (en ms) que tomó cada pieza de código para leer los archivos.

La diferencia de rendimiento entre los dos enfoques de C++ es mínima y no debería cualquier diferencia en la práctica. El rendimiento del código C es lo que hace que el benchmark sea impresionante y puede ser un cambio de juego en términos de velocidad.

                             10K lines     100K lines     1000K lines
Loop with std::getline()         105ms          894ms          9773ms
Boost code                       106ms          968ms          9561ms
C code                            23ms          243ms          2397ms

introduzca la descripción de la imagen aquí

 4
Author: HugoTeixeira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-31 02:03:02

Aunque no es necesario cerrar el archivo manualmente, es buena idea hacerlo si el alcance de la variable de archivo es mayor:

    ifstream infile(szFilePath);

    for (string line = ""; getline(infile, line); )
    {
        //do something with the line
    }

    if(infile.is_open())
        infile.close();
 0
Author: Vijay Bansal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-01 20:11:33

Con argumentos de línea de comandos:

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"

using namespace std;

int main (int argc, char *argv[]) 
{
    vector<string> list;
    ifstream in_stream;
    string line;
    in_stream.open(argv[1]);

    while(!in_stream.eof())
    {
        in_stream >> line;
        list.push_back(line);
    }
    in_stream.close();
    print(list);
    sort(list.begin(), list.end());
    print(list);
}
 -3
Author: Alex Spencer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-31 12:55:57