C++ 把数组数据存入 CSV 文件,以及读取 CSV 文件的数据

1. CSV-百度百科

2. 代码

#pragma once

//Microsoft Visual Studio 2015 Enterprise

#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>

using namespace std;

template<typename base_T>
class modifyCSVfile
{
private:
    struct arrInfo
    {
        double **arrName;
        int lineNum;
        int rowNum;
    };
public:
    string saveArray(base_T* arr, int lineNum, int rowNum, string fileName, int precis = 6);
    string saveArray(const vector<vector<base_T>>& arr, string fileName, int precis = 6);
    vector<vector<double>> CSVtoVector(string fileName);
    arrInfo CSVtoArray(string fileName);
    int delArray(arrInfo);
};


//*************************************************************************************************************************************************************
//*************************************************************************************************************************************************************
template<typename base_T>
string modifyCSVfile<base_T>::saveArray(base_T* arr, int lineNum, int rowNum, string fileName, int precis)
//函数功能:把一个int/float/double型二维数组,存入CSV文件
//参数1:数组第一个元素地址,e.g.【&array1[0][0]】;参数2:数组行数;参数3:数组列数;参数4:文件名;参数5:设置精度(默认精度是6)
{
    fileName += ".csv";    //保存成VSV格式文件,方便用Excel打开

                           //保存数组到文件。如果文件不存在,创建文件,并写入数据;如果文件存在,清空重新写入
    ofstream fout;
    fout.open(fileName.c_str(), ios_base::trunc);
    fout << showpoint;
    fout.precision(precis);
    for (int i = 0; i < lineNum; i++)
    {
        for (int j = 0; j < rowNum; j++)
        {
            if (j < rowNum - 1)
                fout << *(arr + i * rowNum + j) << ",";        // arr + i * rowNum + j:找到当前数组元素的顺序索引值
            else
                fout << *(arr + i * rowNum + j) << endl;
        }
    }
    fout.close();
    return fileName;
}

////用法示例:Visual Studio 2017 Community
//#include<iostream>
//#include<fstream>
//#include<string>
//#include<vector>
//#include"modifyCSVfile.h"
//
//const int arr_lineNum = 5;
//const int arr_rowNum = 7;
//int main()
//{
//    //定义一个double型二维数组,并赋值
//    double k = 1.1;
//    double arr[arr_lineNum][arr_rowNum];
//    for (int i = 0; i < arr_lineNum; i++)
//    {
//        for (int j = 0; j < arr_rowNum; j++)
//        {
//            arr[i][j] = k;
//            k = k + 1;
//        }
//    }
//
//    //输出当前数组到屏幕
//    for (int i = 0; i < arr_lineNum; i++)
//    {
//        for (int j = 0; j < arr_rowNum; j++)
//        {
//            cout << arr[i][j] << " ";
//        }
//        cout << endl;
//    }
//    system("pause");
//
//    //把当前数组存如文件。文件位置:当前工程文件夹下。文件格式为.csv,可用文本文档打开,也可用Excel打开。
//    modifyCSVfile<double> save;
//    save.saveArray(&arr[0][0], arr_lineNum, arr_rowNum, "arr1", 6);
//
//    return 0;
//}


//*************************************************************************************************************************************************************
//*************************************************************************************************************************************************************
template<typename base_T>
string modifyCSVfile<base_T>::saveArray(const vector<vector<base_T>>& arr, string fileName, int precis)
//函数功能:把一个vector二维数组,存入CSV文件
//参数1:vector对象名;参数2:文件名;参数3:设置精度(默认精度是6)
{
    fileName += ".csv";    //保存成VSV格式文件,方便用Excel打开

                           //保存数组到文件。如果文件不存在,创建文件,并写入数据;如果文件存在,清空重新写入
    ofstream fout;
    fout.open(fileName.c_str(), ios_base::trunc);
    fout << showpoint;
    fout.precision(precis);
    for (unsigned int i = 0; i < arr.size(); i++)
    {
        for (unsigned int j = 0; j < arr[i].size(); j++)
        {
            if (j <  arr[i].size() - 1)
                fout << arr[i][j] << ",";
            else
                fout << arr[i][j] << endl;
        }
    }
    fout.close();
    return fileName;
}

////用法示例:Visual Studio 2017 Community
//#include<iostream>
//#include<fstream>
//#include<string>
//#include<vector>
//#include"modifyCSVfile.h"
//
//int main()
//{
//    //定义一个二维vector数组,并赋值
//    double k = 1.1;
//    int lineNum = 5, rowNum = 7;
//    vector<vector<double> > arr2(lineNum, vector<double>(rowNum));
//    for (int i = 0; i < lineNum; i++)
//    {
//        for (int j = 0; j < rowNum; j++)
//        {
//            arr2[i][j] = k;
//            k = k + 1;
//        }
//    }
//
//    //输出当前数组到屏幕
//    for (int i = 0; i < lineNum; i++)
//    {
//        for (int j = 0; j < rowNum; j++)
//            cout << arr2[i][j] << " ";
//        cout << endl;
//    }
//    system("pause");
//
//    //把当前数组存如文件。文件位置:当前工程文件夹下。文件格式为.csv,可用文本文档打开,也可用Excel打开。
//    modifyCSVfile<double> save;
//    save.saveArray(arr2, "arr2", 6);
//
//    return    0;
//}

//*************************************************************************************************************************************************************
//*************************************************************************************************************************************************************
template<typename base_T>
vector<vector<double>> modifyCSVfile<base_T>::CSVtoVector(string fileName)
//函数功能:读取只包含数据不包含文字的CSV文件,并取出里边的数据存入到二维double型vector数组中
//参数1:文件名
{
    fileName += ".csv";
    ifstream fin;
    fin.open(fileName.c_str(), ios_base::in);        //以只读的方式打开文件

                                                     //跳过CSV文件开头可能出现的空行
    char ch;
    while (fin.get(ch))
    {
        if (ch == '\n')
            continue;
        else
            break;
    }
    streamoff pos = fin.tellg();            //保存当前位置
    fin.seekg(pos - 1, ios_base::beg);        //返回到文件中有数据开始的那一行的首位

                                              //获取CSV文件中数据的行数
    int lineNum = 0, rowNum = 0;
    string buf;
    while (getline(fin, buf) && !buf.empty())
    {
        lineNum = lineNum + 1;
    }
    fin.clear();        //getline()读取到文件尾,接下来输入流被阻断。需要重置输入流,如果不重置,接下来将无法获取文件数据。

                        //获取CSV文件中数据的列数
    fin.seekg(pos - 1, ios_base::beg);        //返回到文件中有数据开始的那一行的首位
    while (fin.get(ch))
    {
        if (ch == ',')
        {
            rowNum = rowNum + 1;
        }
        else
            if (ch == '\n')
                break;
    }
    rowNum = rowNum + 1;

    //把CSV文件中的数据存入double型的vector中
    fin.seekg(pos - 1, ios_base::beg);        //返回到文件中有数据开始的那一行的首位
    buf.erase(0);
    double temp;
    vector<vector<double>>vect(lineNum, vector<double>(rowNum));
    for (int i = 0; i < lineNum; i++)
    {
        for (int j = 0; j < rowNum; j++)
        {
            while (fin.get(ch))
            {
                if (ch != ',' && ch != '\n')
                    buf += ch;
                else
                {
                    temp = atof(buf.c_str());
                    vect[i][j] = temp;
                    buf.erase(0);
                    break;
                }
            }
        }
    }
    fin.close();

    return vect;
}

////用法示例:Visual Studio 2017 Community
//#include<iostream>
//#include<fstream>
//#include<string>
//#include<vector>
//#include<cstdio>
//#include<cstdlib>
//#include"modifyCSVfile.h"
//
//using namespace std;
//
//int main()
//{
//
//    vector<vector<double>> arr1;        //创建一个二维vector数组,用于接受函数调用返回的二维vector数组
//    modifyCSVfile<double> read;
//    arr1 = read.CSVtoVector("arr2");
//
//    //输出arr1到屏幕
//    for (int i = 0; i < 4; i++)
//    {
//        for (int j = 0; j < 4; j++)
//        {
//            cout << arr1[i][j] << " ";
//        }
//        cout << endl;
//    }
//
//    system("pause");
//    return    0;
//}


//*************************************************************************************************************************************************************
//*************************************************************************************************************************************************************
template<typename base_T>
typename modifyCSVfile<base_T>::arrInfo modifyCSVfile<base_T>::CSVtoArray(string fileName)
//函数功能:读取只包含数据不包含文字的CSV文件,并取出里边的数据存入到new创建的动态二维数组中
//参数1:文件名
{
    fileName += ".csv";
    ifstream fin;
    fin.open(fileName.c_str(), ios_base::in);        //以只读的方式打开文件

                                                     //跳过CSV文件开头可能出现的空行
    char ch;
    while (fin.get(ch))
    {
        if (ch == '\n')
            continue;
        else
            break;
    }
    streamoff pos = fin.tellg();            //保存当前位置
    fin.seekg(pos - 1, ios_base::beg);        //返回到文件中有数据开始的那一行的首位

                                              //获取CSV文件中数据的行数
    int lineNum = 0, rowNum = 0;
    string buf;
    while (getline(fin, buf) && !buf.empty())
    {
        lineNum = lineNum + 1;
    }
    fin.clear();        //getline()读取到文件尾,接下来输入流被阻断。需要重置输入流,如果不重置,接下来将无法获取文件数据。

                        //获取CSV文件中数据的列数
    fin.seekg(pos - 1, ios_base::beg);        //返回到文件中有数据开始的那一行的首位
    while (fin.get(ch))
    {
        if (ch == ',')
        {
            rowNum = rowNum + 1;
        }
        else
            if (ch == '\n')
                break;
    }
    rowNum = rowNum + 1;

    //new创建二维动态数组
    double **arr = new double *[lineNum];
    for (int i = 0; i < lineNum; i++)
    {
        arr[i] = new double[rowNum];
    }

    //把CSV文件中的数据存入二维数组中
    fin.seekg(pos - 1, ios_base::beg);        //返回到文件中有数据开始的那一行的首位
    buf.erase(0);
    double temp;
    for (int i = 0; i < lineNum; i++)
    {
        for (int j = 0; j < rowNum; j++)
        {
            while (fin.get(ch))
            {
                if (ch != ',' && ch != '\n')
                    buf += ch;
                else
                {
                    temp = atof(buf.c_str());
                    arr[i][j] = temp;
                    buf.erase(0);
                    break;
                }
            }
        }
    }
    fin.close();

    //创建一个结构对象,保存:指向当前数组的指针、当前数组行数、当前数组列数
    arrInfo info;
    info.arrName = arr;
    info.lineNum = lineNum;
    info.rowNum = rowNum;

    return info;        //返回结构
}

////用法示例:Visual Studio 2017 Community
//#include<iostream>
//#include<fstream>
//#include<string>
//#include<vector>
//#include<cstdio>
//#include<cstdlib>
//#include"modifyCSVfile.h"
//
//using namespace std;
//
//int main()
//{
//    //读取CSV文件arr2中的数据,返回一个结构。结构包括:指向数组的指针、数组行数、数组列数
//    modifyCSVfile<double> read;
//    auto arr1 = read.CSVtoArray("arr2");
//
//    //输出数组数据到屏幕
//    for (int i = 0; i < arr1.lineNum; i++)
//    {
//        for (int j = 0; j < arr1.rowNum; j++)
//        {
//            cout << arr1.arrName[i][j] << " ";
//        }
//        cout << endl;
//    }
//
//    //注意:由于调用CSVtoArray函数时,生成的数组是用new分配的,所以数据用完之后要记得释放。
//    //这里没有释放,可以调用delArray函数释放。
//
//    system("pause");
//    return    0;
//}


//*************************************************************************************************************************************************************
//*************************************************************************************************************************************************************
template<typename base_T>
int modifyCSVfile<base_T>::delArray(arrInfo info)
//函数功能:删除调用CSVtoArray函数时生成的动态二维数组
//由于CSVtoArray函数里边的二维数组是使用new创建的,所以用完之后要释放
{
    for (int i = 0; i < info.lineNum; i++)
        delete[] info.arrName[i];
    delete[] info.arrName;

    return 0;
}

////用法示例:Visual Studio 2017 Community
//#include<iostream>
//#include<fstream>
//#include<string>
//#include<vector>
//#include<cstdio>
//#include<cstdlib>
//#include"modifyCSVfile.h"
//
//using namespace std;
//
//int main()
//{
//    //读取CSV文件arr2中的数据,返回一个结构。结构包括:指向数组的指针、数组行数、数组列数
//    modifyCSVfile<double> read;
//    auto arr1 = read.CSVtoArray("arr2");
//
//    //输出数组数据到屏幕
//    for (int i = 0; i < arr1.lineNum; i++)
//    {
//        for (int j = 0; j < arr1.rowNum; j++)
//        {
//            cout << arr1.arrName[i][j] << " ";
//        }
//        cout << endl;
//    }
//
//    //释放调用CSVtoArray函数时用new生成的动态二维数组
//    modifyCSVfile<double> del;
//    del.delArray(arr1);
//
//    system("pause");
//    return    0;
//}


未完 ......

点击访问原文(进入后根据右侧标签,快速定位到本文)

猜你喜欢

转载自www.cnblogs.com/sinicheveen/p/12009847.html