从 x 列到 y 列以及从第 1 行到第 2 行 c++ 提取 csv 数据
Posted
技术标签:
【中文标题】从 x 列到 y 列以及从第 1 行到第 2 行 c++ 提取 csv 数据【英文标题】:Extract csv data from column x to column y, and from row 1 to row 2 c++ 【发布时间】:2018-03-08 20:33:15 【问题描述】:我有一个 .csv 文件,比如说 1000 行和 1200 列。
如何从所需的列中提取数据,比如 67,到另一列,比如 890。 同时从一行,比如说 9,到另一行,比如说 789,然后用 C++ 将数据导出为新的 csv 文件?
我还是初学者,但熟悉 for 或 while 循环,我可以读取文件。
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
ifstream csvFile;
csvFile.open("../example.csv");
if (csvFile.is_open())
string line;
while(getline(csvFile, line))
//what to do here
else
cout << "Sorry, the file could not be openend." <<endl;
return -1;
csvFile.close();
return 0;
编辑 例如源 csv 文件:
a,1,11,111
b,2,22,222
c,3,33,333
d,4,44,444
假设我们只想要从第 2 列到第 3 列以及从第 2 行到第 3 行,那么结果是一个新的 csv 文件,如下所示:
2,22
3,33
【问题讨论】:
【参考方案1】:有多种方法可以做到这一点。首先想到的是将您的.csv
文件读入vector<string>
的向量中,以便将每个行/列值存储在一个二维数组中,例如向量的向量容器。 (例如std::vector<std::vector<string>> array;
)。这使您可以使用getline
和stringstream
在读取的行上轻松解析.csv
文件(以','
分隔)。
然后您可以编写一个提取函数,该函数引用您存储的 csv 值并使用基于范围的迭代器对各个向量和字符串进行迭代。此时,只需保留行索引和列索引,并在所需范围内输出所需范围和列之间的所有行值即可。一个简单的函数看起来类似于:
void extract (vector<vector<string>>const & array, size_t r1, size_t c1,
size_t r2, size_t c2)
size_t ridx = 0; /* row index */
for (auto& row : array) /* range based row iterator */
size_t cidx = 0; /* column index */
if (r1 <= ridx && ridx <= r2) /* if in row range */
for (auto& col : row) /* range based col iterator */
if (c1 <= cidx && cidx <= c2) /* if in col range */
if (cidx > c1) /* if greater than 1st */
cout << ","; /* output separator */
cout << col; /* output value */
cidx++; /* increment col index */
cout << "\n"; /* output newline */
ridx++; /* increment row index */
if (ridx > r2) /* break if row > r2 */
break;
您可以让它创建一个二级字符串向量以返回以供进一步处理,或者您可以像上面那样简单地输出值(或写入另一个文件)。
将各个部分放在一个简短的示例中,该示例读取您的 csv 文件,并在您的问题中显示的第 1 行、第 1 行和第 2 行和第 2 行之间输出,您可以执行以下操作:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using std::ifstream;
using std::cout;
using std::cerr;
using std::string;
using std::stringstream;
using std::vector;
void extract (vector<vector<string>>const & array, size_t r1, size_t c1,
size_t r2, size_t c2)
size_t ridx = 0; /* row index */
for (auto& row : array) /* range based row iterator */
size_t cidx = 0; /* column index */
if (r1 <= ridx && ridx <= r2) /* if in row range */
for (auto& col : row) /* range based col iterator */
if (c1 <= cidx && cidx <= c2) /* if in col range */
if (cidx > c1) /* if greater than 1st */
cout << ","; /* output separator */
cout << col; /* output value */
cidx++; /* increment col index */
cout << "\n"; /* output newline */
ridx++; /* increment row index */
if (ridx > r2) /* break if row > r2 */
break;
int main (int argc, char **argv)
string line;
vector<vector<string>> array;
if (argc < 2)
cerr << "error: insufficient input.\n"
"usage: " << argv[0] << " filename\n";
return 1;
ifstream f (argv[1]); /* open file */
if (!f.is_open())
perror (("error while opening file " + string(argv[1])).c_str());
return 1;
while (getline (f, line)) /* read each line */
string val; /* string to hold value */
vector<string> row; /* vector for row of values */
stringstream s (line); /* stringstream to parse csv */
while (getline (s, val, ',')) /* for each value */
row.push_back (val); /* add to row */
array.push_back (row); /* add row to array */
f.close();
cout << "complete array\n\n";
for (auto& row : array) /* iterate over rows */
for (auto& val : row) /* iterate over vals */
cout << val << " "; /* output value */
cout << "\n"; /* tidy up with '\n' */
cout << "\nextracted array\n\n";
extract (array, 1, 1, 2, 2); /* extract from 1,1 to 2,2 */
return 0;
(注意:基于范围的循环是 C++11 的一项功能,因此请在编译字符串中添加 -std=c++11
)
您不必将整个文件读入存储。您可以在初始读取行期间轻松保持行数和列数,并使用stringstream
解析列,并且只用您希望输出的值填充array
,或者只输出当时的值,但是通过将extract
例程封装在一个函数中,您可以根据需要对 csv 文件的多个不同范围进行操作。这完全取决于你。完整读取只是让您可以选择输出文件的尽可能多的不同部分,而无需对原始文件执行多次 I/O。
使用/输出示例
$ ./bin/iostream_sstream_csv dat/extract.csv
complete array
a 1 11 111
b 2 22 222
c 3 33 333
d 4 44 444
extracted array
2,22
3,33
可能有更多的 C++ 方法可以将所需的行和列索引括起来,而不是保持简单的行索引和列索引,但每次都有效。您可以查看distance()
或从您的vector.begin()
中减去当前迭代器,但适用的迭代器存在限制。好的旧索引不在乎。
查看一下,如果您还有其他问题,请告诉我。
【讨论】:
【参考方案2】:我想主要问题是如何从给定的列/原始数据中捕获数据/变量: 1.需要定义“范围”和它
2 用“value2()”取数据
关于外观,它不能“同时”:您必须确定程序目标。谢谢!
很抱歉,这段代码插入不太习惯,所以我放了一张图片:
enter image description here
【讨论】:
目标是从 csv 源文件的总范围中选择一个定义的范围,然后将这些数据写入一个新的 csv 文件 或者只将整个csv文件分割成指定的列数,然后将这些生成的文件写入csv文件,然后可以在许多在线服务网站的帮助下进行正常的行分割 我在想两个嵌套的for循环,外循环取水平范围,内循环取垂直范围 非常好,有两个最佳循环。除了为整个 fike 获得的范围之外,请考虑再增加一个范围,以处理每个单元格值以上是关于从 x 列到 y 列以及从第 1 行到第 2 行 c++ 提取 csv 数据的主要内容,如果未能解决你的问题,请参考以下文章