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(涂聚文)