Leer archivo CSV en C++

Jinku Hu 12 octubre 2023
Leer archivo CSV en C++

Este artículo explicará varios métodos de cómo leer un archivo CSV en C++.

Utilice std::getline y std::istringstream para leer el archivo CSV en C++

El archivo CSV se conoce comúnmente como formato de archivo de texto, donde los valores están separados por comas en cada línea. Las líneas se denominan registros de datos y, por lo general, cada registro consta de más de un campo, separados por comas. El formato CSV se usa principalmente para almacenar datos tabulares, por lo que contiene un número igual de delimitadores de coma en cada registro. Sin embargo, tenga en cuenta que, dado que existen múltiples implementaciones en la práctica, uno podría encontrar, por ejemplo, espacios entre los campos separados por comas, o puede que no haya espacios entre los campos, etc. En el siguiente ejemplo, asumimos que no hay espacios entre los campos. Por tanto, cada carácter entre comas se considera una única unidad de datos.

Primero, necesitamos leer el contenido del archivo y almacenarlo en un objeto std::string. La función readFileIntoString utiliza std::ostringstream y rdbuf para leer el archivo y devolver el valor de la string a la función de llamada. Una vez que el paso anterior se realiza con éxito, podemos construir un std::istringstream a partir del objeto string e iterar sobre cada línea. En esta iteración, colocamos otro bucle para extraer cada campo en una línea y almacenarlos en un std::vector. Al final de cada iteración de línea, almacenamos el vector en el std::map y borramos el vector para el siguiente bucle. Tenga en cuenta que std::map se puede sustituir por un vector de vectores o cualquier otra estructura de datos personalizada que sea óptima para el escenario específico.

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>

using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;
using std::ostringstream;
using std::string;

string readFileIntoString(const string& path) {
  auto ss = ostringstream{};
  ifstream input_file(path);
  if (!input_file.is_open()) {
    cerr << "Could not open the file - '" << path << "'" << endl;
    exit(EXIT_FAILURE);
  }
  ss << input_file.rdbuf();
  return ss.str();
}

int main() {
  string filename("grades.csv");
  string file_contents;
  std::map<int, std::vector<string>> csv_contents;
  char delimiter = ',';

  file_contents = readFileIntoString(filename);

  istringstream sstream(file_contents);
  std::vector<string> items;
  string record;

  int counter = 0;
  while (std::getline(sstream, record)) {
    istringstream line(record);
    while (std::getline(line, record, delimiter)) {
      items.push_back(record);
    }

    csv_contents[counter] = items;
    items.clear();
    counter += 1;
  }

  exit(EXIT_SUCCESS);
}

El bucle externo while llama a getline con un delimitador predeterminado, un carácter de nueva línea, mientras que el bucle interno especifica un carácter de coma como tercer argumento. A diferencia del código de muestra anterior, el siguiente implementa la solución para tratar los espacios finales en los campos y analizar las unidades de datos antes de almacenarlas en el vector. Por lo tanto, agregamos el modismo borrar-eliminar al bucle interno while justo antes de que se llame a push_back. Esto se ocupará de cualquier carácter de espacios en blanco como espacios, tabulaciones, retornos de carro y otros, ya que usamos el objeto de función isspace como el argumento remove_if.

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>

using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;
using std::ostringstream;
using std::string;

string readFileIntoString(const string& path) {
  auto ss = ostringstream{};
  ifstream input_file(path);
  if (!input_file.is_open()) {
    cerr << "Could not open the file - '" << path << "'" << endl;
    exit(EXIT_FAILURE);
  }
  ss << input_file.rdbuf();
  return ss.str();
}

int main() {
  string filename("grades.csv");
  string file_contents;
  std::map<int, std::vector<string>> csv_contents;
  char delimiter = ',';

  file_contents = readFileIntoString(filename);

  istringstream sstream(file_contents);
  std::vector<string> items;
  string record;

  int counter = 0;
  while (std::getline(sstream, record)) {
    istringstream line(record);
    while (std::getline(line, record, delimiter)) {
      record.erase(std::remove_if(record.begin(), record.end(), isspace),
                   record.end());
      items.push_back(record);
    }

    csv_contents[counter] = items;
    items.clear();
    counter += 1;
  }

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - C++ File