BSD 3-Clause "New" or "Revised" License

项目介绍

d99kris/rapidcsv 是一个托管在 GitHub 上的开源项目,主要使用 C++ 编写,采用 BSD 3-Clause "New" or "Revised" License 许可证,目前获得 1.1k 个 Star、201 次 Fork。

仓库全名
d99kris/rapidcsv
开源许可证
BSD 3-Clause "New" or "Revised" License
Star 数
1.1k
Fork 数
201
未关闭 Issue
1

README 摘要

Rapidcsv ======== Linux | Mac | Windows | Rapidcsv is an easy-to-use C++ CSV parser library. It supports C++11 (and later), is header-only and comes with a basic test suite. The library was featured in the book C++20 for Programmers. Example Usage ============= Here is a simple example reading a CSV file and getting 'Close' column as a vector of floats. colhdr.csv content: ex001.cpp content: Refer to section More…

完整内容见 GitHub 原始 README 或本页 。

常见问题

rapidcsv 用什么语言开发?

主要使用 C++ 编写,采用 BSD 3-Clause "New" or "Revised" License 许可证,目前有 1.1k 个 Star。

rapidcsv 可以免费商用吗?

仓库采用 BSD 3-Clause "New" or "Revised" License 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 rapidcsv 的源码?

可以直接克隆仓库:git clone https://github.com/d99kris/rapidcsv.git,默认分支为 master;安装与运行步骤见仓库 README。

rapidcsv 最近还在维护吗?

仓库最近一次更新为 1 周前,当前有 1 个未关闭 Issue;Star 数为 1.1k,可作为社区活跃度的参考。

简要分析

热度分
1503
价值分
710
活跃状态
活跃

语言占比

Batchfile
C++
CMake
Shell

Release

README

Rapidcsv

Linux Mac Windows
Linux macOS Windows

Rapidcsv is an easy-to-use C++ CSV parser library. It supports C++11 (and later), is header-only and comes with a basic test suite.

The library was featured in the book C++20 for Programmers.

Example Usage

Here is a simple example reading a CSV file and getting ‘Close’ column as a vector of floats.

colhdr.csv content:

Open,High,Low,Close,Volume,Adj Close
64.529999,64.800003,64.139999,64.620003,21705200,64.620003
64.419998,64.730003,64.190002,64.620003,20235200,64.620003
64.330002,64.389999,64.050003,64.360001,19259700,64.360001
64.610001,64.949997,64.449997,64.489998,19384900,64.489998
64.470001,64.690002,64.300003,64.620003,21234600,64.620003

ex001.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  rapidcsv::Document doc("examples/colhdr.csv");

  std::vector<float> col = doc.GetColumn<float>("Close");
  std::cout << "Read " << col.size() << " values." << std::endl;
}

Refer to section More Examples below for more examples. The tests directory also contains many simple usage examples.

Supported Platforms

Rapidcsv is implemented using C++11 with the intention of being portable. It’s tested on:

  • macOS Sonoma 14.7
  • Ubuntu 24.04 LTS
  • Windows Server / Visual Studio 2022

Installation

Simply copy src/rapidcsv.h to your project/include directory and include it.

Rapidcsv is also available via vcpkg and conan package managers.

More Examples

Several of the following examples are also provided in the examples/ directory and can be executed directly under Linux and macOS. Example running ex001.cpp:

./examples/ex001.cpp

Reading a File with Column and Row Headers

By default rapidcsv treats the first row as column headers, and the first column is treated as data. This allows accessing columns using their labels, but not rows or cells (only using indices). In order to treat the first column as row headers one needs to use LabelParams and set pRowNameIdx to 0.

Column and Row Headers

colrowhdr.csv content:

Date,Open,High,Low,Close,Volume,Adj Close
2017-02-24,64.529999,64.800003,64.139999,64.620003,21705200,64.620003
2017-02-23,64.419998,64.730003,64.190002,64.620003,20235200,64.620003
2017-02-22,64.330002,64.389999,64.050003,64.360001,19259700,64.360001
2017-02-21,64.610001,64.949997,64.449997,64.489998,19384900,64.489998
2017-02-17,64.470001,64.690002,64.300003,64.620003,21234600,64.620003

ex002.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  rapidcsv::Document doc("examples/colrowhdr.csv", rapidcsv::LabelParams(0, 0));

  std::vector<float> close = doc.GetRow<float>("2017-02-22");
  std::cout << "Read " << close.size() << " values." << std::endl;

  long long volume = doc.GetCell<long long>("Volume", "2017-02-22");
  std::cout << "Volume " << volume << " on 2017-02-22." << std::endl;
}

Row Headers Only

rowhdr.csv content:

2017-02-24,64.529999,64.800003,64.139999,64.620003,21705200,64.620003
2017-02-23,64.419998,64.730003,64.190002,64.620003,20235200,64.620003
2017-02-22,64.330002,64.389999,64.050003,64.360001,19259700,64.360001
2017-02-21,64.610001,64.949997,64.449997,64.489998,19384900,64.489998
2017-02-17,64.470001,64.690002,64.300003,64.620003,21234600,64.620003

ex003.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  rapidcsv::Document doc("examples/rowhdr.csv", rapidcsv::LabelParams(-1, 0));

  std::vector<std::string> row = doc.GetRow<std::string>("2017-02-22");
  std::cout << "Read " << row.size() << " values." << std::endl;
}

No Headers

nohdr.csv content:

64.529999,64.800003,64.139999,64.620003,21705200,64.620003
64.419998,64.730003,64.190002,64.620003,20235200,64.620003
64.330002,64.389999,64.050003,64.360001,19259700,64.360001
64.610001,64.949997,64.449997,64.489998,19384900,64.489998
64.470001,64.690002,64.300003,64.620003,21234600,64.620003

ex004.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  rapidcsv::Document doc("examples/nohdr.csv", rapidcsv::LabelParams(-1, -1));

  std::vector<float> close = doc.GetColumn<float>(5);
  std::cout << "Read " << close.size() << " values." << std::endl;

  long long volume = doc.GetCell<long long>(4, 2);
  std::cout << "Volume " << volume << " on 2017-02-22." << std::endl;
}

Reading a File with Custom Separator

For reading of files with custom separator (i.e. not comma), one need to specify the SeparatorParams argument. The following example reads a file using semi-colon as separator.

semi.csv content:

Date;Open;High;Low;Close;Volume;Adj Close
2017-02-24;64.529999;64.800003;64.139999;64.620003;21705200;64.620003
2017-02-23;64.419998;64.730003;64.190002;64.620003;20235200;64.620003
2017-02-22;64.330002;64.389999;64.050003;64.360001;19259700;64.360001
2017-02-21;64.610001;64.949997;64.449997;64.489998;19384900;64.489998
2017-02-17;64.470001;64.690002;64.300003;64.620003;21234600;64.620003

ex005.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  rapidcsv::Document doc("examples/semi.csv", rapidcsv::LabelParams(0, 0),
                          rapidcsv::SeparatorParams(';'));

  std::vector<float> close = doc.GetColumn<float>("Close");
  std::cout << "Read " << close.size() << " values." << std::endl;

  long long volume = doc.GetCell<long long>("Volume", "2017-02-22");
  std::cout << "Volume " << volume << " on 2017-02-22." << std::endl;
}

Supported Get/Set Data Types

The internal cell representation in the Document class is using std::string and when other types are requested, standard conversion routines are used. All standard conversions are relatively straight-forward, with the exception of char for which rapidcsv interprets the cell’s (first) byte as a character. The following example illustrates the supported data types.

colrowhdr.csv content:

Date,Open,High,Low,Close,Volume,Adj Close
2017-02-24,64.529999,64.800003,64.139999,64.620003,21705200,64.620003
2017-02-23,64.419998,64.730003,64.190002,64.620003,20235200,64.620003
2017-02-22,64.330002,64.389999,64.050003,64.360001,19259700,64.360001
2017-02-21,64.610001,64.949997,64.449997,64.489998,19384900,64.489998
2017-02-17,64.470001,64.690002,64.300003,64.620003,21234600,64.620003

ex006.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  rapidcsv::Document doc("examples/colrowhdr.csv", rapidcsv::LabelParams(0, 0));

  std::cout << doc.GetCell<std::string>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<int>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<long>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<long long>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<unsigned>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<unsigned long>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<unsigned long long>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<float>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<double>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<long double>("Volume", "2017-02-22") << std::endl;
  std::cout << doc.GetCell<char>("Volume", "2017-02-22") << std::endl;
}

Global Custom Data Type Conversion

One may override conversion routines (or add new ones) by implementing ToVal() and/or ToStr(). Below is an example overriding int conversion, to instead provide two decimal fixed-point numbers. Also see tests/test035.cpp for a test overriding ToVal() and ToStr().

ex008.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

namespace rapidcsv
{
  template<>
  void Converter<int>::ToVal(const std::string& pStr, int& pVal) const
  {
    pVal = static_cast<int>(roundf(100.0f * std::stof(pStr)));
  }
}

int main()
{
  rapidcsv::Document doc("examples/colrowhdr.csv", rapidcsv::LabelParams(0, 0));

  std::vector<int> close = doc.GetColumn<int>("Close");
  std::cout << "close[0]  = " << close[0] << std::endl;
  std::cout << "close[1]  = " << close[1] << std::endl;
}

Custom Data Type Conversion Per Call

It is also possible to override conversions on a per-call basis, enabling more flexibility. This is illustrated in the following example. Additional conversion override usage can be found in the test tests/test063.cpp

ex009.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

void ConvFixPoint(const std::string& pStr, int& pVal)
{
  pVal = static_cast<int>(roundf(100.0f * std::stof(pStr)));
}

struct MyStruct
{
  int val = 0;
};

void ConvMyStruct(const std::string& pStr, MyStruct& pVal)
{
  pVal.val = static_cast<int>(roundf(100.0f * std::stof(pStr)));
}

int main()
{
  rapidcsv::Document doc("examples/colrowhdr.csv", rapidcsv::LabelParams(0, 0));

  std::cout << "regular         = " << doc.GetCell<int>("Close", "2017-02-21") << "\n";
  std::cout << "fixpointfunc    = " << doc.GetCell<int>("Close", "2017-02-21", ConvFixPoint) << "\n";

  auto convFixLambda = [](const std::string& pStr, int& pVal) { pVal = static_cast<int>(roundf(100.0f * stof(pStr))); };
  std::cout << "fixpointlambda  = " << doc.GetCell<int>("Close", "2017-02-21", convFixLambda) << "\n";

  std::cout << "mystruct        = " << doc.GetCell<MyStruct>("Close", "2017-02-21", ConvMyStruct).val << "\n";
}

Reading CSV Data from a Stream or String

In addition to specifying a filename, rapidcsv supports constructing a Document from a stream and, indirectly through stringstream, from a string. File streams used with rapidcsv should be opened in std::ios::binary mode to enable full functionality. Here is a simple example reading CSV data from a string:

ex007.cpp content:

#include <iostream>
#include <vector>
#include "rapidcsv.h"

int main()
{
  const std::string& csv =
    "Date,Open,High,Low,Close,Volume,Adj Close\n"
    "2017-02-24,64.529999,64.800003,64.139999,64.620003,21705200,64.620003\n"
    "2017-02-23,64.419998,64.730003,64.190002,64.620003,20235200,64.620003\n"
    "2017-02-22,64.330002,64.389999,64.050003,64.360001,19259700,64.360001\n"
    "2017-02-21,64.610001,64.949997,64.449997,64.489998,19384900,64.489998\n"
    "2017-02-17,64.470001,64.690002,64.300003,64.620003,21234600,64.620003\n"
    ;

  std::stringstream sstream(csv);
  rapidcsv::Document doc(sstream, rapidcsv::LabelParams(0, 0));

  std::vector<float> close = doc.GetColumn<float>("Close");
  std::cout << "Read " << close.size() << " values." << std::endl;

  long long volume = doc.GetCell<long long>("Volume", "2017-02-22");
  std::cout << "Volume " << volume << " on 2017-02-22." << std::endl;
}

Reading a File with Invalid Numbers (e.g. Empty Cells) as Numeric Data

By default rapidcsv throws an exception if one tries to access non-numeric data as a numeric data type, as it basically propagates the underlying conversion routines’ exceptions to the calling application.

The reason for this is to ensure data correctness. If one wants to be able to read data with invalid numbers as numeric data types, one can use ConverterParams to configure the converter to default to a numeric value. The value is configurable and by default it’s std::numeric_limits::signaling_NaN() for float types, and 0 for integer types. Example:

rapidcsv::Document doc("file.csv", rapidcsv::LabelParams(),
                        rapidcsv::SeparatorParams(),
                        rapidcsv::ConverterParams(true));

Check if a Column Exists

Rapidcsv provides the methods GetColumnNames() and GetRowNames() to retrieve the column and row names. To check whether a particular column name exists one can for example do:

rapidcsv::Document doc("file.csv");
std::vector<std::string> columnNames = doc.GetColumnNames();
bool columnExists =
  (std::find(columnNames.begin(), columnNames.end(), "A") != columnNames.end());

Handling Quoted Cells

By default rapidcsv automatically dequotes quoted cells (i.e. removes the encapsulating " characters from "example quoted cell"). This functionality may be disabled by passing pAutoQuote = false in SeparatorParams, example:

rapidcsv::Document doc("file.csv", rapidcsv::LabelParams(),
                       rapidcsv::SeparatorParams(',' /* pSeparator */,
                                                 false /* pTrim */,
                                                 rapidcsv::sPlatformHasCR /* pHasCR */,
                                                 false /* pQuotedLinebreaks */,
                                                 false /* pAutoQuote */));

Skipping Empty and Comment Lines

Rapidcsv reads all lines by default, but may be called to ignore comment lines starting with a specific character, example:

rapidcsv::Document doc("file.csv", rapidcsv::LabelParams(), rapidcsv::SeparatorParams(),
                       rapidcsv::ConverterParams(),
                       rapidcsv::LineReaderParams(true /* pSkipCommentLines */,
                                                  '#' /* pCommentPrefix */));

Using LineReaderParams it is also possible to skip empty lines, example:

rapidcsv::Document doc("file.csv", rapidcsv::LabelParams(), rapidcsv::SeparatorParams(),
                       rapidcsv::ConverterParams(),
                       rapidcsv::LineReaderParams(false /* pSkipCommentLines */,
                                                  '#' /* pCommentPrefix */,
                                                  true /* pSkipEmptyLines */));

UTF-16 and UTF-8

Rapidcsv’s preferred encoding for non-ASCII text is UTF-8. UTF-16 LE and UTF-16 BE can also be read and written, using the byte order mark of a loaded file to automatically detect its encoding. Documents loaded as UTF-16 are converted to UTF-8 internally, and converted back to their original UTF-16 encoding when saved.

Limiting Maximum Document Size

Rapidcsv does not limit the amount of data read by default. As each parsed cell has some memory overhead, malformed input may expand to much more memory than the size of the input data. Applications reading untrusted input may define RAPIDCSV_MAX_COUNT before including rapidcsv.h, in order to set an upper limit for the number of rows or columns read and throw exception std::out_of_range when exceeded.

CMake

Rapidcsv may be included in a CMake project using various methods:

Locale Independent Parsing

Rapidcsv uses locale-dependent conversion functions when parsing float values by default. It is possible to configure rapidcsv to use locale independent parsing by setting mNumericLocale in ConverterParams, see for example tests/test087.cpp

API Documentation

The following classes makes up the Rapidcsv interface:

Technical Details

Rapidcsv uses cmake for its tests. Commands to build and execute the test suite:

mkdir -p build && cd build && cmake -DRAPIDCSV_BUILD_TESTS=ON .. && make && ctest -C unit --output-on-failure && ctest -C perf --verbose ; cd -

Rapidcsv uses doxygenmd to generate its Markdown API documentation:

doxygenmd src doc

Rapidcsv uses Uncrustify to ensure consistent code formatting:

uncrustify -c uncrustify.cfg --no-backup src/rapidcsv.h

Alternatives

There are many CSV parsers for C++, for example:

License

Rapidcsv is distributed under the BSD 3-Clause license. See LICENSE file.

Contributions

Bugs, PRs, etc are welcome on the GitHub project page https://github.com/d99kris/rapidcsv

Keywords

c++, c++11, csv parser, comma separated values, single header library.

评论

暂无评论