Lea el archivo línea por línea usando ifstream en C++

9 minutos de lectura

Lea el archivo linea por linea usando ifstream en C
duquevin

Los contenidos de file.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 proceso estos datos línea por línea en C++?

Puedo obtener la primera línea, pero ¿cómo obtengo la siguiente línea del archivo?

ifstream myfile;
myfile.open ("file.txt");

Lea el archivo linea por linea usando ifstream en C
Kerrek SB

Primero, haz 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 ficha por ficha:

    int a, b;
    while (infile >> a >> b)
    {
        // process pair (a,b)
    }
    
  2. Análisis basado en líneas, utilizando 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 falsas si usa getline() después de que la extracción basada en tokens ya lo llevó al final de una línea.

  • @EdwardKarak: No entiendo qué significa “comas como token”. Las comas no representan números enteros.

    – KerrekSB

    18/10/2014 a las 14:22

  • el OP usó un espacio para delimitar los dos enteros. Quería saber si while (infile >> a >> b) funcionaría si el OP usara a como delimitador de coma, porque ese es el escenario en mi propio programa

    –Edward Karak

    18/10/2014 a las 14:46

  • @EdwardKarak: Ah, entonces cuando dijiste “token” quisiste decir “delimitador”. Derecha. Con una coma, dirías: int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))

    – KerrekSB

    18/10/2014 a las 15:25


  • @KerrekSB: Ah. Me equivoqué. No sabía que podía hacer eso. Podría tener algún código propio para reescribir.

    – marca h

    06/01/2015 a las 15:00

  • Para una explicación de la while(getline(f, line)) { } construir y con respecto al manejo de errores, eche un vistazo a este (mi) artículo: gehrcke.de/2011/06/… (Creo que no necesito tener mala conciencia al publicar esto aquí, incluso es un poco anterior a esta respuesta).

    – Dr. Jan-Philip Gehrcke

    18 de enero de 2015 a las 14:15


1647652509 825 Lea el archivo linea por linea usando ifstream en C
K-ballo

Utilizar ifstream para leer datos de un archivo:

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

Si realmente necesita leer línea por línea, haga esto:

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

Pero probablemente solo necesites extraer pares de coordenadas:

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

Actualizar:

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

  • Su solución ha mejorado un poco: su variable de línea no es visible después de la lectura del archivo en contraste con la segunda solución de Kerrek SB, que también es una solución buena y simple.

    – DanielTuzes

    23 de julio de 2013 a las 14:24

  • getline es en string verasí que no olvides el #include <string>

    – mxmlnkn

    12 de julio de 2017 a las 23:02

1642608489 276 Java lista solo los subdirectorios de un directorio no los
HugoTeixeira

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

[Fast] Bucle con std::getline()

El enfoque más simple es abrir un std::ifstream y hacer 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 (std::getline(file, line)) {
        // using printf() in all tests for consistency
        printf("%s", line.c_str());
    }
    file.close();
}

[Fast] Usar 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 del 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();
        }
    }
}

[Fastest] Usar 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 el punto de referencia 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);

Punto de referencia — ¿Cuál es más rápido?

Hice 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 de líneas y 10.000.000 de líneas de texto. Cada línea de texto contiene 10 palabras en promedio. El programa está compilado con -O3 optimización y su salida se enví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 el printf() función de consistencia.

Los resultados muestran el tiempo (en ms) que tardó cada fragmento de código en leer los archivos.

La diferencia de rendimiento entre los dos enfoques de C++ es mínima y no debería marcar ninguna diferencia en la práctica. El rendimiento del código C es lo que hace que el punto de referencia sea impresionante y puede cambiar las reglas del 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

ingrese la descripción de la imagen aquí

  • ¿Qué sucede si elimina la sincronización de C++ con C en las salidas de la consola? Es posible que esté midiendo una desventaja conocida del comportamiento predeterminado de std::cout contra printf.

    – usuario4581301

    30 de julio de 2018 a las 20:41

  • Gracias por traer esta inquietud. He vuelto a hacer las pruebas y el rendimiento sigue siendo el mismo. He editado el código para usar el printf() funcionar en todos los casos por consistencia. También he intentado usar std::cout en todos los casos y esto no hizo absolutamente ninguna diferencia. Como acabo de describir en el texto, la salida del programa va a /dev/null por lo que no se mide el tiempo de impresión de las líneas.

    – Hugo Teixeira

    31 de julio de 2018 a las 2:11

  • maravilloso Gracias. Me pregunto dónde está la desaceleración.

    – usuario4581301

    31 de julio de 2018 a las 4:34

  • Hola @HugoTeixeira, sé que este es un hilo antiguo, traté de replicar tus resultados y no pude ver ninguna diferencia significativa entre c y c++ github.com/simonsso/readfile_benchmarks

    – Simón

    3 de febrero de 2019 a las 5:24

  • @Fareanor Eso no es correcto. Solo afecta a la estándar flujos de C++, std::ifstream file no es uno de ellos. es.cppreference.com/w/cpp/io/ios_base/sync_with_stdio

    – usuario202729

    15 de junio de 2020 a las 1:16

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

struct CoordinatePair
{
    int x;
    int y;
};

Luego 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 puede 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
}

1647652511 68 Lea el archivo linea por linea usando ifstream en C
gsamaras

Ampliando la respuesta aceptada, si la entrada es:

1,NYC
2,ABQ
...

aún podrá 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();

1647652511 956 Lea el archivo linea por linea usando ifstream en C
Universo

Esta respuesta es para Visual Studio 2017 y si desea leer del archivo de texto qué ubicación es relativa a su aplicación de consola compilada.

primero coloque su archivo de texto (test.txt en este caso) en su carpeta de solución. Después de compilar, mantenga el archivo de texto en la misma carpeta con applicationName.exe

C:\Users\”username”\source\repos\”solutionName”\”solutionName”

#include <iostream>
#include <fstream>

using namespace std;
int main()
{
    ifstream inFile;
    // open the file stream
    inFile.open(".\\test.txt");
    // check if opening a file failed
    if (inFile.fail()) {
        cerr << "Error opeing a file" << endl;
        inFile.close();
        exit(1);
    }
    string line;
    while (getline(inFile, line))
    {
        cout << line << endl;
    }
    // close the file stream
    inFile.close();
}

1647652512 505 Lea el archivo linea por linea usando ifstream en C
Vijay Bansal

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

    ifstream infile(szFilePath);

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

    if(infile.is_open())
        infile.close();

  • No estoy seguro de que esto mereciera un voto negativo. OP pidió una forma de obtener cada línea. Esta respuesta hace eso y da un gran consejo para asegurarse de que el archivo se cierre. Para un programa simple, puede que no sea necesario, pero al menos un GRAN hábito para formar. Tal vez podría mejorarse agregando algunas líneas de código para procesar las líneas individuales que extrae, pero en general es la respuesta más simple a la pregunta de los OP.

    – Xandor

    18 sep 2019 a las 18:22

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad