cpp: read csv file
// CSVfilemanagement.h :
//练习案例:CSV 文件读写
//
// 2023年4月5日 涂聚文 Geovin Du edit.
// https://www.digitalocean.com/community/tutorials/getline-in-c-plus-plus
// https://www.geeksforgeeks.org/csv-file-management-using-c/
// https://codereview.stackexchange.com/questions/211826/code-to-read-and-write-csv-files
// https://thispointer.com/how-to-read-data-from-a-csv-file-in-c/
// https://github.com/vincentlaucsb/csv-parser
//https://codereview.stackexchange.com/questions/211826/code-to-read-and-write-csv-files
//https://www.geeksforgeeks.org/csv-file-management-using-c/
//https://github.com/awdeorio/csvstream
//https://cplusplus.com/forum/general/282647/
//https://cplusplus.com/forum/beginner/221913/
//https://www.example-code.com/cpp/csv_update.asp
//https://www.chilkatsoft.com/dotnet-core.asp
//https://www.codeproject.com/articles/741183/cplusplus-minimalistic-csv-streams#history
//https://github.com/iamantony/qtcsv
//
//https://sourceforge.net/projects/cccsvparser/
//https://github.com/ben-strasser/fast-cpp-csv-parser
//https://www.codeproject.com/articles/741183/cplusplus-minimalistic-csv-streams
//https://en.cppreference.com/w/cpp/header/filesystem
//
//
//
//
//
//
//
//
//
//
#pragma once
#ifndef CSVFILEMANAGEMENT_H
#define CSVFILEMANAGEMENT_H
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <string>
/**
* @brief
* \author geovindu.
* \date 20230-4-10
*/
namespace geovindu
{
/**
* @brief CSV 文件操作
* .
*/
class CSVfilemanagement
{
private:
public:
/// <summary>
///
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
//string ReverseString(string& s);
/// <summary>
///
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
//string readFileIntoDuString(string path);
/// <summary>
///
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
//string readTextFileIntoString(const string& path);
/// <summary>
///
/// </summary>
void getReadFile();
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
/// <param name="dataset"></param>
void write_csv(std::string filename, std::vector<std::pair<std::string, std::vector<int>>> dataset);
std::vector<std::pair<std::string, std::vector<int>>> read_csv(std::string filename);
/// <summary>
///
/// </summary>
/// <param name="line_data"></param>
void DisplayRowCsv(std::vector<std::string> line_data);
/**
* @brief 写.
*
*/
void create();
/**
* @brief 读.
*
*/
void read_record();
/// <summary>
/// 读取全部记录
/// </summary>
void readAll();
/**
* @brief 更新.
*
*/
void update_recode();
/**
* @brief 删除.
*
*/
void delete_record();
};
}
#endif
// CSVfilemanagement.cpp :
//练习案例:CSV 文件读写
//
// 2023年4月5日 涂聚文 Geovin Du edit.
//
//
#include "CSVfilemanagement.h"
#include <memory>
#include <string> // std::string
#include <fstream> // std::ofstream, std::ifstream
#include <vector> // std::vector
#include <utility> // std::pair
#include <stdexcept> // std::runtime_error
#include <sstream> // std::stringstream
#include <iostream> // std::cout, std::cin
#include <map>
#include <algorithm>
#include <iterator>
//#include <bits/stdc++.h>
using std::cout; using std::endl;
using std::string; using std::reverse;
using namespace std;
/**
* @brief
* \author geovindu.
* \date 20230-4-10
*/
namespace geovindu
{
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
string ReverseString(string& s) {
string rev(s.rbegin(), s.rend());
return rev;
}
/// <summary>
/// text file
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
string readTextFileIntoString(string path) {
ifstream input_file(path);
if (!input_file.is_open()) {
cerr << "Could not open the file - '"
<< path << "'" << endl;
exit(EXIT_FAILURE);
}
return string((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>());
}
/// <summary>
/// csv file
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
string readFileIntoDuString(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();
}
/// <summary>
///
/// </summary>
/// <param name="file"></param>
void CSVfilemanagement::getReadFile()
{
string filename("reportcard.csv"); //"grades.csv"
string file_contents;
std::map<int, std::vector<string>> csv_contents;
char delimiter = ',';
file_contents = readFileIntoDuString(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);
// std::cout << record << std::endl;
}
csv_contents[counter] = items;
std::cout << csv_contents[counter].size() << std::endl;
items.clear();
counter += 1;
}
}
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
/// <param name="dataset"></param>
void CSVfilemanagement::write_csv(std::string filename, std::vector<std::pair<std::string, std::vector<int>>> dataset) {
// Make a CSV file with one or more columns of integer values
// Each column of data is represented by the pair <column name, column data>
// as std::pair<std::string, std::vector<int>>
// The dataset is represented as a vector of these columns
// Note that all columns should be the same size
// Create an output filestream object
std::ofstream myFile(filename);
// Send column names to the stream
for (int j = 0; j < dataset.size(); ++j)
{
myFile << dataset.at(j).first;
if (j != dataset.size() - 1) myFile << ","; // No comma at end of line
}
myFile << "\n";
// Send data to the stream
for (int i = 0; i < dataset.at(0).second.size(); ++i)
{
for (int j = 0; j < dataset.size(); ++j)
{
myFile << dataset.at(j).second.at(i);
if (j != dataset.size() - 1) myFile << ","; // No comma at end of line
}
myFile << "\n";
}
// Close the file
myFile.close();
}
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
std::vector<std::pair<std::string, std::vector<int>>> CSVfilemanagement::read_csv(std::string filename) {
// Reads a CSV file into a vector of <string, vector<int>> pairs where
// each pair represents <column name, column values>
// Create a vector of <string, int vector> pairs to store the result
std::vector<std::pair<std::string, std::vector<int>>> result;
// Create an input filestream
std::ifstream myFile(filename);
// Make sure the file is open
if (!myFile.is_open()) throw std::runtime_error("Could not open file");
// Helper vars
std::string line, colname;
int val;
// Read the column names
if (myFile.good())
{
// Extract the first line in the file
std::getline(myFile, line);
// Create a stringstream from line
std::stringstream ss(line);
// Extract each column name
while (std::getline(ss, colname, ',')) {
// Initialize and add <colname, int vector> pairs to result
result.push_back({ colname, std::vector<int> {} });
}
}
// Read data, line by line
while (std::getline(myFile, line))
{
// Create a stringstream of the current line
std::stringstream ss(line);
// Keep track of the current column index
int colIdx = 0;
// Extract each integer
while (ss >> val) {
// Add the current integer to the 'colIdx' column's values vector
result.at(colIdx).second.push_back(val);
// If the next token is a comma, ignore it and move on
if (ss.peek() == ',') ss.ignore();
// Increment the column index
colIdx++;
}
}
// Close file
myFile.close();
return result;
}
/**
* @brief 写.
*
*/
void CSVfilemanagement::create()
{
// file pointer
fstream fout;
// opens an existing csv file or creates a new file.
fout.open("reportcard.csv", ios::out | ios::app);
cout << "Enter the details of students:"
<< " roll(序号) name(姓名) maths(数学) phy(物理) chem(化学) bio(生物)"
<< endl;
int i, roll, phy, chem, math, bio;
string name;
int num = 0;
char yes = 'Y';
while (1)
{
cout << "序号" << endl;
cin >> roll;
cout << "姓名" << endl;
cin >> name;
cout << "数学" << endl;
cin >> math;
cout << "物理" << endl;
cin >> phy;
cout << "化学" << endl;
cin >> chem;
cout << "生物" << endl;
cin >> bio;
// Insert the data to file
fout << roll << ", "
<< name << ", "
<< math << ", "
<< phy << ", "
<< chem << ", "
<< bio
<< "\n";
cout << "是否继续输入学生信息:(Y/N)" << endl;
cin >> yes;
if (yes == 'N' || yes == 'n')
{
break;
}
num++;
}
// Read the input
/*
for (i = 0; i < 1; i++) {
cout << "序号" << endl;
cin >> roll;
cout << "姓名" << endl;
cin >> name;
cout << "数学" << endl;
cin >> math;
cout << "物理" << endl;
cin >> phy;
cout << "化学" << endl;
cin >> chem;
cout << "生物" << endl;
cin >> bio;
// Insert the data to file
fout << roll << ", "
<< name << ", "
<< math << ", "
<< phy << ", "
<< chem << ", "
<< bio
<< "\n";
}
*/
fout.close();
}
/// <summary>
///
/// </summary>
/// <param name="line_data"></param>
void CSVfilemanagement::DisplayRowCsv(std::vector<std::string> line_data)
{
std::cout << line_data[0]<<"\t\t"
<< line_data[1] << "\t\t"
<< line_data[2] << "\t\t"
<< line_data[3] << "\t\t"
<< line_data[4] << "\t\t"
<< line_data[5]
<< std::endl;
/* cout << "Details of Roll " << line_data[0] << " : \n";
cout << "Name: " << line_data[1] << "\n";
cout << "Maths: " << line_data[2] << "\n";
cout << "Physics: " << line_data[3] << "\n";
cout << "Chemistry: " << line_data[4] << "\n";
cout << "Biology: " << line_data[5] << "\n";*/
}
/// <summary>
/// 读全部记录
/// </summary>
void CSVfilemanagement::readAll()
{
// File pointer
fstream fin;
// Open an existing file
fin.open("reportcard.csv", ios::in);
if (!fin.is_open())
{
std::cout << "Error: opening file fail(没有找到文件)" << std::endl;
std::exit(1);
}
// Get the roll number
// of which the data is required
int rollnum, roll2, count = 0;
cout << "Enter the roll number(行号) "
<< "of the student to display details: ";
cin >> rollnum;
// Read the Data from the file
// as String Vector
vector<string> row;
string line, word, temp,headtile;
std::vector<std::string> words; //声明一个字符串向量
std::vector<std::string> headwords;
std::istringstream sin;
// std::string word;
// ------------读取数据-----------------
// 读取标题行
std::getline(fin, line);
sin.str(line);
while (std::getline(sin, headtile, ','))//将字符串流sin中的字符读到field字符串中,以逗号为分隔符
{
headwords.push_back(headtile);
}
for (auto headstr : headwords)
{
cout << headstr << "\t\t";
}
cout << "\n";
/*
cout << headwords[0] << "\t\t"
<< headwords[1] << "\t\t"
<< headwords[2] << "\t\t"
<< headwords[3] << "\t\t"
<< headwords[4] << "\t\t"
<< headwords[5] << "\n";*/
// 按行读取数据
while (std::getline(fin, line))
{
// 清空vector,只存当前行的数据
words.clear();
sin.clear();
sin.str(line);
while (std::getline(sin, word, ',')) //将字符串流sin中的字符读到field字符串中,以逗号为分隔符
{
//std::cout << word << std::endl;
words.push_back(word); //将每一格中的数据逐个push
}
DisplayRowCsv(words);
}
}
/**
* @brief 读、查找.
*
*/
void CSVfilemanagement::read_record()
{
// File pointer
fstream fin;
// Open an existing file
fin.open("reportcard.csv", ios::in);
if (!fin.is_open())
{
std::cout << "Error: opening file fail(没有找到文件)" << std::endl;
std::exit(1);
}
// Get the roll number
// of which the data is required
int rollnum, roll2, count = 0;
cout << "Enter the roll number(行号) "
<< "of the student to display details: ";
cin >> rollnum;
// Read the Data from the file
// as String Vector
vector<string> row;
string line, word, temp;
while (fin >> temp) {
row.clear();
//行
//line = rollnum;
// read an entire row and
// store it in a string variable 'line'
//读取标题
// used for breaking words
stringstream s(line);
// read every column data of a row and
// store it in a string variable, 'word'
//std::getline(std::cin, name);
// if (!word.empty())
//{
while (std::getline(s, word, ',')) {
// add all the column data
// of a row to a vector
row.push_back(word);
}
// }
// convert string to integer for comparision
roll2 = stoi(row[0]);
// Compare the roll number
if (roll2 == rollnum) {
// Print the found data
count = 1;
cout << "Details of Roll " << row[0] << " : \n";
cout << "Name: " << row[1] << "\n";
cout << "Maths: " << row[2] << "\n";
cout << "Physics: " << row[3] << "\n";
cout << "Chemistry: " << row[4] << "\n";
cout << "Biology: " << row[5] << "\n";
break;
}
}
if (count == 0)
cout << "Record not found\n";
fin.close();
}
/// <summary>
///
/// </summary>
void CSVfilemanagement::update_recode()
{
// File pointer
fstream fin, fout;
// Open an existing record
fin.open("reportcard.csv", ios::in);
// Create a new file to store updated data
fout.open("reportcardnew.csv", ios::out);
int rollnum, roll1, marks, count = 0, i;
char sub;
int index, new_marks;
string line, word;
vector<string> row;
// Get the roll number from the user
cout << "Enter the roll number "
<< "of the record to be updated: ";
cin >> rollnum;
// Get the data to be updated
cout << "Enter the subject "
<< "to be updated(M/P/C/B): ";
cin >> sub;
// Determine the index of the subject
// where Maths has index 2,
// Physics has index 3, and so on
if (sub == 'm' || sub == 'M')
index = 2;
else if (sub == 'p' || sub == 'P')
index = 3;
else if (sub == 'c' || sub == 'C')
index = 4;
else if (sub == 'b' || sub == 'B')
index = 5;
else {
cout << "Wrong choice.Enter again\n";
this->update_recode();// update_record();
}
// Get the new marks
cout << "Enter new marks: ";
cin >> new_marks;
// Traverse the file
while (!fin.eof()) {
row.clear();
getline(fin, line);
stringstream s(line);
//std::getline();
while (std::getline(s, word, ',')) {
row.push_back(word);
}
roll1 = stoi(row[0]);
int row_size = row.size();
if (roll1 == rollnum) {
count = 1;
stringstream convert;
// sending a number as a stream into output string
convert << new_marks;
// the str() converts number into string
row[index] = convert.str();
if (!fin.eof()) {
for (i = 0; i < row_size - 1; i++) {
// write the updated data
// into a new file 'reportcardnew.csv'
// using fout
fout << row[i] << ", ";
}
fout << row[row_size - 1] << "\n";
}
}
else {
if (!fin.eof()) {
for (i = 0; i < row_size - 1; i++) {
// writing other existing records
// into the new file using fout.
fout << row[i] << ", ";
}
// the last column data ends with a '\n'
fout << row[row_size - 1] << "\n";
}
}
if (fin.eof())
break;
}
if (count == 0)
cout << "Record not found\n";
fin.close();
fout.close();
// removing the existing file
remove("reportcard.csv");
// renaming the updated file with the existing file name
rename("reportcardnew.csv", "reportcard.csv");
}
/// <summary>
///
/// </summary>
void CSVfilemanagement::delete_record()
{
// Open FIle pointers
fstream fin, fout;
// Open the existing file
fin.open("reportcard.csv", ios::in);
// Create a new file to store the non-deleted data
fout.open("reportcardnew.csv", ios::out);
int rollnum, roll1, marks, count = 0, i;
char sub;
int index, new_marks;
string line, word;
vector<string> row;
// Get the roll number
// to decide the data to be deleted
cout << "Enter the roll number "
<< "of the record to be deleted: ";
cin >> rollnum;
// Check if this record exists
// If exists, leave it and
// add all other data to the new file
while (!fin.eof()) {
row.clear();
getline(fin, line);
stringstream s(line);
while (std::getline(s, word, ',')) {
row.push_back(word);
}
int row_size = row.size();
roll1 = stoi(row[0]);
// writing all records,
// except the record to be deleted,
// into the new file 'reportcardnew.csv'
// using fout pointer
if (roll1 != rollnum) {
if (!fin.eof()) {
for (i = 0; i < row_size - 1; i++) {
fout << row[i] << ", ";
}
fout << row[row_size - 1] << "\n";
}
}
else {
count = 1;
}
if (fin.eof())
break;
}
if (count == 1)
cout << "Record deleted\n";
else
cout << "Record not found\n";
// Close the pointers
fin.close();
fout.close();
// removing the existing file
remove("reportcard.csv");
// renaming the new file with the existing file name
rename("reportcardnew.csv", "reportcard.csv");
}
}
/// <summary>
///
/// </summary>
void Geovin::Displaycsv()
{
// Open file
csvstream csvin("input.csv");
// Rows have key = column name, value = cell datum
map<string, string> row;
std::map<std::string, string>::iterator it = row.begin();
// Extract the "animal" column
cout << "动物名称" << "\t\t" << "动物类型" << endl;
while (csvin >> row) {
cout << row["name"]<<"\t\t"<< row["animal"] << "\n";
}
while (it != row.end())
{
cout << "I:" << it->first << it->second << endl;
//string st = it->first;
//cout << st << endl;
//break;
}
}
/// <summary>
///
/// </summary>
void Geovin::DisplayAtemDemo()
{
ATMdemo atem;
atem.setATM();
}
/// <summary>
/// csv 操作
/// </summary>
void Geovin::CsvCreate()
{
CSVfilemanagement csv;
//string geovindu=csv.readFileIntoDuString("reportcard.csv");
//csv.getReadFile();
//csv.create();
csv.readAll();
//csv.read_record();
}
调用:
geovin.Displaycsv(); //ATM //geovin.DisplayAtemDemo(); geovin.CsvCreate();
输出:


哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号