OpenCSV快速方便导出CSV文件【拿虾C++】

项目源代码:https://github.com/OpenMiniServer/opencsv

使用C++分析大数据的时候,数据按CSV格式导出,可以用Excel分析数据。
OpenCSV非常易用和简单。
测试例子:

#include <assert.h>
#include "opencsv.h"

int main()
{
    std::string buffer1;
    std::string buffer2;

    //生成CSV数据
    {
        OpenCSV csv = { "ID", "name", "salary" };
        csv = { "1", "Jack", "100000" };
        csv = { "2", "Tom", "80000" };
        csv = { std::to_string(3), "Lucy", "50000" };

        csv >> buffer1;
    }
    
    buffer2 = "ID,name,salary\n"
            "1,Jack,100000\n"
            "2,Tom,80000\n"
            "3,Lucy,50000\n";

    assert(buffer1 == buffer2);

    //解析CSV数据
    {
        OpenCSV csv;
        csv << buffer2;
        buffer1 = "ID,name,salary\n";
        for (size_t i = 1; i < csv.size(); ++i)
        {
            auto& line = csv[i];
            buffer1.append(line["ID"] + "," + line["name"] + "," + line["salary"] + "\n");
        }
    }
    assert(buffer1 == buffer2);
    
    std::string filePath = "./test.csv";
    //生成CSV文件
    {
        OpenCSV csv;
        csv << buffer2;
        assert(csv[0][0] == "ID");
        assert(csv[0][2] == "salary");
        csv[1]["salary"] = std::to_string(10000);
        csv[2]["salary"] = "8000";
        csv[3]["salary"] = "5000";
        csv >> filePath; //自动判断是否是路径
    }
    buffer2 = "ID,name,salary\n"
        "1,Jack,10000\n"
        "2,Tom,8000\n"
        "3,Lucy,5000\n";
    //加载CSV文件
    {
        OpenCSV csv;
        csv << filePath; //自动判断是否是路径
        buffer1.clear();
        csv >> buffer1;
    }
    assert(buffer1 == buffer2);
    return 0;
}

跨平台支持:
Windows、linux
源文件列表:
src/opencsv.h
src/opencsv.cpp
运行测试例子

cd ./opencsv
mkdir build
cd build
cmake ..
make
./test

源文件:
src/opencsv.h

/***************************************************************************
 * Copyright (C) 2023-, openlinyou, <linyouhappy@outlook.com>
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 ***************************************************************************/

#ifndef HEADER_OPEN_CSV_H
#define HEADER_OPEN_CSV_H

#include <string>
#include <vector>

class OpenCSV
{
    typedef std::vector<std::string> Line;

    class CSVLine
    {
        Line line_;
        OpenCSV* csv_;
        CSVLine()
            :csv_(0) {}
        friend class OpenCSV;
    public:
        CSVLine(OpenCSV* csv)
            :csv_(csv){}
        CSVLine(const CSVLine& csvline)
        {
            csv_ = csvline.csv_;
            if (!csvline.line_.empty())
            {
                line_ = csvline.line_;
            }
        }
        inline size_t size() { return line_.size(); }
        inline bool empty() { return line_.empty(); }
        inline Line& line() { return line_; }
        std::string& operator[](size_t idx);
        std::string& operator[](const std::string& key);
    };

    typedef const std::initializer_list<std::string> List;
    std::vector<CSVLine> lines_;
    std::string emptyStr_;
    friend class CSVLine;
public:
    OpenCSV() {}
    OpenCSV(List& list);
    void operator=(List& list);

    //OpenCSV(OpenCSV& csv);
    //void operator=(OpenCSV& csv);

    inline bool empty() { return lines_.empty(); }
    inline size_t size() { return lines_.size(); }

    CSVLine& operator[](size_t idx);
    void operator>>(std::string& output);
    void operator<<(const std::string& output);

    inline std::vector<CSVLine>& lines() { return lines_; }
};

#endif /* HEADER_OPEN_CSV_H */

src/opencsv.cpp

#include "opencsv.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <string>
#include <vector>

static bool CheckFilePath(const std::string& filePath);
static int64_t ReadFile(const std::string& filePath, std::string& buffer, const char* m);
static int64_t WriteFile(const std::string& filePath, std::string& buffer, const char* m);

std::string& OpenCSV::CSVLine::operator[](size_t idx)
{
    if (idx >= line_.size())
    {
        line_.resize(idx + 1);
    }
    return line_[idx];
}

std::string& OpenCSV::CSVLine::operator[](const std::string& key)
{
    OpenCSV* csv = dynamic_cast<OpenCSV*>(csv_);
    if (csv == 0 || csv->lines_.empty())
    {
        static std::string emptyStr;
        assert(false);
        return emptyStr;
    }
    CSVLine& keyLine = csv->lines_[0];
    size_t idx = 0;
    for (; idx < keyLine.size(); ++idx)
    {
        if (keyLine[idx] == key) break;
    }
    if (idx < keyLine.size())
    {
        return line_[idx];
    }
    assert(false);
    csv->emptyStr_.clear();
    return csv->emptyStr_;
}

OpenCSV::OpenCSV(List& list)
{
    if (list.size() > 0)
    {
        lines_.resize(lines_.size() + 1, CSVLine(this));
        lines_.back().line() = list;
    }
}

void OpenCSV::operator=(List& list)
{ 
    if (list.size() > 0)
    {
        lines_.resize(lines_.size() + 1, CSVLine(this));
        lines_.back().line() = list;
    }
}

//OpenCSV::OpenCSV(OpenCSV& csv)
//{
//    lines_ = csv.lines();
//}

//void OpenCSV::operator=(OpenCSV& csv)
//{
//    lines_ = csv.lines();
//}

OpenCSV::CSVLine& OpenCSV::operator[](size_t idx)
{
    if (idx >= lines_.size())
    {
        lines_.resize(idx + 1, CSVLine(this));
    }
    return lines_[idx];
}

void OpenCSV::operator>>(std::string& output)
{
    std::string str;
    for (auto& line : lines_)
    {
        if (line.empty()) continue;
        for (size_t j = 0; j < line.size(); ++j)
        {
            str.append(j > 0 ? "," + line[j] : line[j]);
        }
        str.append("\n");
    }
    if (!CheckFilePath(output))
    {
        output.append(str);
        return;
    }
    WriteFile(output, str, "wb");
}

void OpenCSV::operator<<(const std::string& input)
{
    std::string buffer;
    if (CheckFilePath(input))
    {
        ReadFile(input, buffer, "rb");
    }
    else
    {
        buffer = input;
    }
    lines_.clear();
    if (buffer.empty()) return;
    size_t row    = 0;
    size_t column = 0;
    for (size_t i = 0; i < buffer.size(); ++i)
    {
        if (buffer[i] == '\n')
        {
            if (!lines_.back().empty())
            {
                ++row;
            }
            column = 0;
            continue;
        }
        if (buffer[i] == ',')
        {
            ++column;
            continue;
        }
        (*this)[row][column].push_back(buffer[i]);
    }
}

static bool CheckFilePath(const std::string& filePath)
{
    if (!filePath.empty() && filePath.size() < 1024)
    {
        if (!strstr(filePath.c_str(), "\n") && !strstr(filePath.c_str(), ","))
        {
            if (strstr(filePath.c_str(), "/")) return true;
        }
    }
    return false;
}

static int64_t ReadFile(const std::string& filePath, std::string& buffer, const char* m)
{
    FILE* f = fopen(filePath.c_str(), m);
    if (!f) return -1;
    fseek(f, 0, SEEK_END);
    long len = ftell(f);
    fseek(f, 0, SEEK_SET);
    buffer.resize(len, 0);
    size_t ret = fread((void*)buffer.data(), 1, len, f);
    fclose(f);
    return ret == 0 ? -1 : len;
}

static int64_t WriteFile(const std::string& filePath, std::string& buffer, const char* m)
{
    FILE* f = fopen(filePath.c_str(), m);
    if (!f) return -1;
    size_t ret = fwrite((void*)buffer.data(), 1, buffer.size(), f);
    fclose(f);
    return ret == 0 ? -1 : buffer.size();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值