Leggi il file CSV in C++
Questo articolo spiegherà diversi metodi su come leggere un file CSV in C++.
Usa std::getline
e std::istringstream
per leggere il file CSV in C++
Il file CSV è comunemente noto come formato di file di testo, in cui i valori sono separati da virgole in ogni riga. Le righe sono chiamate record di dati e ogni record è solitamente costituito da più di un campo, separati da virgole. Il formato CSV viene utilizzato principalmente per memorizzare dati tabulari, quindi contiene un numero uguale di delimitatori virgola in ogni record. Nota tuttavia, poiché nella pratica ci sono più implementazioni, si potrebbero trovare, ad esempio, spazi tra i campi separati da virgole, o potrebbero non esserci spazi tra i campi, ecc. Nell’esempio seguente, si presume che non ci siano spazi tra i campi i campi. Quindi ogni carattere tra virgole è considerato una singola unità di dati.
Per prima cosa, dobbiamo leggere il contenuto del file e memorizzarlo in un oggetto std::string
. La funzione readFileIntoString
utilizza std::ostringstream
e rdbuf
per leggere il file e restituire il valore string
alla funzione chiamante. Una volta che il passaggio precedente è stato eseguito con successo, possiamo costruire uno std::istringstream
dall’oggetto string
e iterare su ogni riga. In questa iterazione, inseriamo un altro bucle per estrarre ogni campo in una riga e memorizzarli in un std::vector
. Alla fine di ogni iterazione di riga, memorizziamo il vettore
in std::map
e cancelliamo il vettore
per il bucle successivo. Nota che std::map
può essere sostituito con un vettore di vettori o qualsiasi altra struttura di dati personalizzata che sarà ottimale per lo scenario specifico.
#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);
}
Il bucle esterno while
chiama getline
con delimitatore predefinito, un nuovo carattere di riga, mentre il bucle interno specifica una virgola come terzo argomento. In contrasto con il codice di esempio precedente, quello successivo implementa la soluzione per gestire gli spazi finali nei campi e analizzare le unità di dati prima di memorizzarle nel vettore
. Quindi, abbiamo aggiunto l’idioma cancella-rimuovi
al cicli while
interno appena prima che venga chiamato push_back
. Questo si occuperà di qualsiasi carattere di spazi bianchi come spazi, tabulazioni, ritorni a capo e altri poiché usiamo l’oggetto funzione isspace
come argomento 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