Ler arquivo CSV em C++

Jinku Hu 12 outubro 2023
Ler arquivo CSV em C++

Este artigo explicará vários métodos de como ler um arquivo CSV em C++.

Use std::getline e std::istringstream para ler o arquivo CSV em C++

O arquivo CSV é comumente conhecido como formato de arquivo de texto, em que os valores são separados por vírgulas em cada linha. As linhas são chamadas de registros de dados e cada registro geralmente consiste em mais de um campo, separados por vírgulas. O formato CSV é usado principalmente para armazenar dados tabulares, portanto, contém um número igual de delimitadores de vírgula em cada registro. No entanto, observe que, uma vez que existem várias implementações na prática, pode-se encontrar, por exemplo, espaços entre os campos separados por vírgula, ou pode não haver espaços entre os campos, etc. No exemplo a seguir, presumimos que não há espaços entre os campos. Assim, cada caractere entre vírgulas é considerado uma unidade de dados única.

Primeiro, precisamos ler o conteúdo do arquivo e armazená-lo em um objeto std::string. A função readFileIntoString utiliza std::ostringstream e rdbuf para ler o arquivo e retornar o valor string para a função do chamador. Uma vez que a etapa anterior é realizada com sucesso, podemos construir um std::istringstream a partir do objeto string e iterar sobre cada linha. Nesta iteração, colocamos outro loop para extrair cada campo em uma linha e armazená-los em um std::vector. No final de cada iteração de linha, armazenamos o vector no std::map e apagamos o vetor para o próximo bucle. Observe que std::map pode ser substituído por um vetor de vetores ou qualquer outra estrutura de dados personalizada que seja ideal para o cenário 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);
}

O loop externo while chama getline com o delimitador padrão, um caractere de nova linha, enquanto o loop interno especifica um caractere de vírgula como terceiro argumento. Em contraste com o código de amostra anterior, o próximo implementa a solução para lidar com espaços à direita em campos e analisar as unidades de dados antes de armazená-los no vetor. Assim, adicionamos o idioma erase-remove ao loop while interno pouco antes de push_back ser chamado. Isso lidará com quaisquer caracteres de espaços em branco como espaços, tabulações, retornos de carro e outros, uma vez que usamos o objeto de função isspace como o 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

Artigo relacionado - C++ File