ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CSV文件处理

2021-08-04 11:32:15  阅读:132  来源: 互联网

标签:std 文件 string 处理 filename file CSV


 目录

 1. CSV文件简单介绍

2. CSV文件的读写操作

  2..1 读CSV文件

    2.1.1 C读取CSV文件

    2.1.2 C++读取CSV文件

    2.1.3 QT读取CSV文件

  2.2 写CSV文件

    2.2.1 C写CSV文件

    2.2.2 C++写CSV文件

    2.2.3 Qt写CSV文件

1. CSV文件简单介绍

  CSV,Comma-Separated Values,翻译过来就是逗号分隔值,也可以称为符号分隔值,因为也可以不是逗号分隔的。CSV文件的内容是以逗号分隔开的一系列数据。CSV文件可用Excel和记事本打开。

  工作中用到CSV文件无非是读和写CSV文件,接下来是关于CSV文件读和写的操作。

2. CSV文件的读写操作

  读CSV文件可以按照读TXT文件去读,写CSV文件时需要注意要确保当前文件的位置是在最后一行。

2.1 读CSV文件

  有的CSV文件是有标题行的,如下。通常是读取需要的内容,标题行舍弃掉。

        

2.1.1 C读取CSV文件

  使用C读取CSV文件需要用到fseek()函数,该函数原型为fseek(FILE* stream,long offset,int fromwhere);

    参数fromwhere表示从什么地方开始,取值有三个,分别是:

设置值 备注
SEEK_SET=0 表示从文件开头
SEEK_CUR=1 表示从文件当前位置
SEEK_END=2 表示从文件末尾

 


#include <stdio.h>
bool ReadCSV(const char* filename)
    {
        FILE *fp = nullptr;
        char *line, *record;
        char buffer[1024];
        if ((fp = fopen(filename, "at+")) != nullptr)
        {
            line = fgets(buffer, sizeof(buffer), fp);  // 1. 获取第一行的内容

            fseek(fp, strlen(line), SEEK_SET);  // 2. 定位到第二行

            while ((line = fgets(buffer, sizeof(buffer), fp)) != nullptr)// 3. 逐行获取文件内容
            {
                record = strtok(line, ",");
                while ((record = strtok(line, ",")) != nullptr)// 4. 分隔每一行的每一个数据
                    printf("%s ", record);// 5. 打印每一行的每一个数据,以空格隔开
                printf("\n");
            }
            fclose(fp);
            fp = nullptr;
            return true;
        }
        else
        {
            printf("Open file fail!");
            return false;
        }
    }

2.1.2 C++读取CSV文件

  使用fstream文件流读取CSV文件。

    使用正则表达式匹配每个单元格的内容,需要添加头文件#include <regex>,

bool ReadCSV_CPP(const std::string& filename)
{
    std::fstream file(filename,std::ios::in);  // 1. 打开文件
    if(!file.is_open())
    {
        std::string exp_string = "Open File FAIL!";
        throw exp_string;
    }
    std::string strline;
    std::smatch sm;
    std::regex rx("(\\w+)");  //CSV文件每个单元格的格式,此处匹配的是字母、数字、下划线
    std::string strtemp;
    while (std::getline(file,strline)) {  // 2. 逐行读取csv文件
        while (std::regex_search(strline, sm, rx))  // 3. 正则表达式匹配每个单元格的内容
        {
            strtemp = sm.begin()->str();  // 4. 匹配到的单元格内的内容
            strline = sm.suffix().str();  // 5. 剩下的字符
            printf("%s ",strtemp.c_str());
        }
        if(!strline.empty())
        {
            strtemp = strline;
            printf("%s ",strtemp.c_str());
        }
        printf("\n");
    }

    file.close();
    return true;
}

2.1.3 QT读取CSV文件

 bool ReadCSV_Qt(const QString& filename)
    {
        QFile file(filename);
        if(!file.open(QFile::ReadOnly | QFile::Text))
        {
            std::string s ="read file fail";
            throw s;
        }

        QStringList content;  // 所有逗号分隔的内容
        content.clear();
        QTextStream text(&file);
        QStringList listContent;  //每行的内容
        while (!text.atEnd()) {
            listContent.push_back(text.readLine());  // 逐行获取每行内容
        }
        for(QString& str:listContent)
        {
            content.push_back(str.split(","));  // 获取每行的逗号分隔开的内容
        }
        file.close();
        return true;
    }

2.2 写CSV文件

  写CSV文件时需要注意当前文件指针位置在文件的最后一行的开始位置。

2.2.1 C写CSV文件

  同样的,C写CSV文件时也会用到fseek()函数,此时fromwhere参数需要设置为SEEK_END,表示文件指针定位到文件末尾。

// data数据类型可以任意为需要保存的内容
bool WriteCSV_C(const char* filename,const char* data)
{
    FILE *pf = nullptr;
    pf = std::freopen(filename, "at", stdout);  // freopen()函数用于文件流重定向
    if (nullptr == pf)
    {
        const char* chErrmsg = "Open File FAIL!";
        throw chErrmsg;
    }
    long longfileSizeTemp = ftell(pf);  // 获取当前文件大小
    size_t datasize = strlen(data);
    fseek(pf, 0, SEEK_END);  //将文件指针定位到文件末尾
    longfileSizeTemp = ftell(pf);
    if (0 == longfileSizeTemp)  // 若文件大小=0表示该文件还未写入数据
    {
        for(int i=0;i<datasize;i++)
        {
            printf("col_%d,",i);// 输入csv的标题内容
        }
    }
    printf("\n");

    for(int i=0;i<datasize;i++)
    {
        printf("%c,",data[i]);// 输入csv的数据内容
    }

    fclose(pf);
    pf = nullptr;

    return true;
}

2.2.2 C++写CSV文件

   使用fstream类写CSV文件,需要使用到seekp()、tellp()获取到文件是否为空。

bool WriteCSV_CPP(const std::string& filename,const std::vector<int>& data)
{
    std::fstream file(filename,std::ios::out|std::ios::app);  // 1. 打开文件,ios::app表示在文件尾追加,如果不加该属性,那么每次写的时候会覆盖文件内容
    if(!file.is_open())
    {
        std::string exp_string = "Open File FAIL!";
        throw exp_string;
    }
    // 以下两行获取文件的大小,首先设置文件流指针位置为末尾,然后返回当前文件写指针的位置,如果为0表示该文件为空
    file.seekp(0,file.end);  // seekp()函数设置输出文件流的文件流指针位置
    size_t filesize =  file.tellp();  // 返回文件写指针的位置
    int iDataSize = data.size();
    if(0 == filesize)
    {
        for(int i=0;i<iDataSize;++i)  // 如果文件为空,添加标题
        {
            file << "col_" << i << ",";
        }
    }
    file << std::endl;

    for(int i=0;i<iDataSize;++i)  // 写入内容
    {
        file << data.at(i) << ",";
    }

    file.close();
    return true;
}

2.2.3 Qt写CSV文件

bool WriteCSV_Qt(const QString& filename,const QStringList& data)
{
    QFile file(filename);
    if(!file.open(QFile::WriteOnly | QFile::Text | QFile::Append))  // 1. 以追加方式打开文件
    {
        std::string s ="Open File FAIL";
        throw s;
    }

    qint64 filesize = file.size();  // 获取文件大小
    int iDataSize = data.size();
    if(0 == filesize)
    {
        QString strTemp;
        for(int i=0;i<iDataSize;++i)  //文件为空时,填入标题
        {
            strTemp.sprintf("col_%d,",i);
            file.write(strTemp.toStdString().c_str());
        }
    }
    file.write("\n");
    for(QString str:data)
    {
        file.write(str.toStdString().c_str());  // 写入文件内容
        file.write(",");
    }

    file.close();
    return true;
}

标签:std,文件,string,处理,filename,file,CSV
来源: https://www.cnblogs.com/Zoya-/p/15074876.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有