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);
}
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