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

  

输出:

 

 

 

posted @ 2023-04-11 19:55  ®Geovin Du Dream Park™  阅读(62)  评论(0)    收藏  举报