当前位置:   article > 正文

CSV文件简介及C++实现_c++ csv库

c++ csv库

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号):其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须象二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

CSV文件格式的通用标准并不存在,但是在RFC 4180中有基础性的描述。使用的字符编码同样没有被指定,但是7-bit ASCII是最基本的通用编码。

CSV是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。最广泛的应用是在程序之间转移表格数据,而这些程序本身是在不兼容的格式上进行操作的(往往是私有的和/或无规范的格式)。因为大量程序都支持某种CSV变体,至少是作为一种可选择的输入/输出格式。

“CSV”并不是一种单一的、定义明确的格式(尽管RFC 4180有一个被通常使用的定义)。因此在实践中,术语”CSV”泛指具有以下特征的任何文件:

(1)、纯文本,使用某个字符集,比如ASCII、Unicode、EBCDIC或GB2312(简体中文)等;

(2)、由记录组成(典型的是每行一条记录);

(3)、每条记录被分隔符分隔为字段(典型分隔符有逗号、分号或制表符;有时分隔符可以包括可选的空格);

(4)、每条记录都有同样的字段序列。

在这些常规的约束条件下,存在着许多CSV变体,故CSV文件并不完全互通。然而,这些变异非常小,并且有许多应用程序允许用户预览文件(这是可行的,因为它是纯文本),然后指定分隔符、转义规则等。如果一个特定CSV文件的变异过大,超出了特定接收程序的支持范围,那么可行的做法往往是人工检查并编辑文件,或通过简单的程序来修复问题。因此在实践中,CSV文件还是非常方便的。

CSV格式最好被用来表现记录集合或序列,其中的每条记录都有完全相同的字段序列。CSV格式没有被限定于某个特定字符集。不管用Unicode还是用ASCII,都没有问题(尽管特定程序支持的CSV可能会有它们自己的局限性)。甚至从一个字符集翻译到另一个字符集,CSV文件都不会有问题(不象几乎所有的私有数据格式)。然而,CSV不提供任何途径来表明使用的是什么字符集。

“CSV”格式中大量变体的存在说明并没有一个”CSV标准”。在常见用法中,几乎任何定界符分隔的文本数据都可以被统称为”CSV”文件。不同的CSV格式可能不会兼容。

以上内容介绍主要来自: 维基百科 

以下code 是参考 https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c ,可以实现对简单csv文件的解析:

如果csv文件比较复杂,可以试试github上的一个开源库:  https://github.com/ben-strasser/fast-cpp-csv-parser

parse_csv.hpp:

  1. #ifndef FBC_CPPBASE_TEST_PARSE_CSV_HPP_
  2. #define FBC_CPPBASE_TEST_PARSE_CSV_HPP_
  3. // reference: https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c?page=1&tab=votes#tab-top
  4. #include <iterator>
  5. #include <iostream>
  6. #include <fstream>
  7. #include <sstream>
  8. #include <vector>
  9. #include <string>
  10. class CSVRow {
  11. public:
  12. std::string const& operator[](std::size_t index) const { return m_data[index]; }
  13. std::size_t size() const { return m_data.size(); }
  14. void readNextRow(std::istream& str)
  15. {
  16. std::string line;
  17. std::getline(str, line);
  18. std::stringstream lineStream(line);
  19. std::string cell;
  20. m_data.clear();
  21. while (std::getline(lineStream, cell, ',')) {
  22. m_data.push_back(cell);
  23. }
  24. // This checks for a trailing comma with no data after it.
  25. if (!lineStream && cell.empty()) {
  26. // If there was a trailing comma then add an empty element.
  27. m_data.push_back("");
  28. }
  29. }
  30. private:
  31. std::vector<std::string> m_data;
  32. };
  33. std::istream& operator>>(std::istream& str, CSVRow& data)
  34. {
  35. data.readNextRow(str);
  36. return str;
  37. }
  38. class CSVIterator {
  39. public:
  40. /*typedef std::input_iterator_tag iterator_category;
  41. typedef CSVRow value_type;
  42. typedef std::size_t difference_type;
  43. typedef CSVRow* pointer;
  44. typedef CSVRow& reference;*/
  45. CSVIterator(std::istream& str) :m_str(str.good() ? &str : nullptr) { ++(*this); }
  46. CSVIterator() :m_str(nullptr) {}
  47. // Pre Increment
  48. CSVIterator& operator++() { if (m_str) { if (!((*m_str) >> m_row)){ m_str = nullptr; } }return *this; }
  49. // Post increment
  50. CSVIterator operator++(int) { CSVIterator tmp(*this); ++(*this); return tmp; }
  51. CSVRow const& operator*() const { return m_row; }
  52. CSVRow const* operator->() const { return &m_row; }
  53. bool operator==(CSVIterator const& rhs) { return ((this == &rhs) || ((this->m_str == nullptr) && (rhs.m_str == nullptr))); }
  54. bool operator!=(CSVIterator const& rhs) { return !((*this) == rhs); }
  55. private:
  56. std::istream* m_str;
  57. CSVRow m_row;
  58. };
  59. #endif // FBC_CPPBASE_TEST_PARSE_CSV_HPP_

test_parse_csv.cpp:

  1. #include "test_parse_cvs.hpp"
  2. #include <iostream>
  3. #include <string>
  4. #include <fstream>
  5. #include <vector>
  6. #include "parse_csv.hpp"
  7. namespace parse_cvs_ {
  8. int test_parse_cvs_1()
  9. {
  10. std::ifstream file("E:/GitCode/Messy_Test/testdata/test_csv.csv");
  11. std::vector<std::vector<std::string>> data;
  12. CSVIterator loop(file);
  13. for (; loop != CSVIterator(); ++loop) {
  14. CSVRow row = *loop;
  15. std::vector<std::string> tmp(row.size());
  16. for (int i = 0; i < row.size(); ++i) {
  17. tmp[i] = row[i];
  18. }
  19. data.emplace_back(tmp);
  20. }
  21. for (int i = 0; i < data.size(); ++i) {
  22. for (int j = 0; j < data[i].size(); ++j) {
  23. fprintf(stdout, "%s\t", data[i][j].c_str());
  24. }
  25. fprintf(stdout, "\n");
  26. }
  27. return 0;
  28. }
  29. } // namespace parse_cvs_

test_csv.csv测试数据如下:

执行结果如下:

 

GitHub: https://github.com/fengbingchun/Messy_Test 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/959226
推荐阅读
相关标签
  

闽ICP备14008679号