我想知道是否有人可以给予我一只手,我试图建立一个程序,读入一个大数据块的浮动与未知大小从csv文件。我已经在MATLAB中写了这个,但想编译和分发它,所以移动到c++。
我只是学习和尝试阅读在这开始
7,5,1989
2,4,2312
从一个文本文件。
代码到目前为止
// Read in CSV
//
// Alex Byasse
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <stdlib.h>
int main() {
unsigned int number_of_lines = 0;
FILE *infile = fopen("textread.csv", "r");
int ch;
int c = 0;
bool tmp = true;
while (EOF != (ch=getc(infile))){
if(',' == ch){
++c;
}
if ('\n' == ch){
if (tmp){
int X = c;
tmp = false;
}
++number_of_lines;
}
}
fclose(infile);
std::ifstream file( "textread.csv" );
if(!file){
std:cerr << "Failed to open File\n";
return 1;
}
const int ROWS = X;
const int COLS = number_of_lines;
const int BUFFSIZE = 100;
int array[ROWS][COLS];
char buff[BUFFSIZE];
std::string line;
int col = 0;
int row = 0;
while( std::getline( file, line ) )
{
std::istringstream iss( line );
std::string result;
while( std::getline( iss, result, ',' ) )
{
array[row][col] = atoi( result.c_str() );
std::cout << result << std::endl;
std::cout << "column " << col << std::endl;
std::cout << "row " << row << std::endl;
col = col+1;
if (col == COLS){
std:cerr << "Went over number of columns " << COLS;
}
}
row = row+1;
if (row == ROWS){
std::cerr << "Went over length of ROWS " << ROWS;
}
col = 0;
}
return 0;
}
我用的matlab代码是>>
fid = fopen(twoDM,'r');
s = textscan(fid,'%s','Delimiter','\n');
s = s{1};
s_e3t = s(strncmp('E3T',s,3));
s_e4q = s(strncmp('E4Q',s,3));
s_nd = s(strncmp('ND',s,2));
[~,cell_num_t,node1_t,node2_t,node3_t,mat] = strread([s_e3t{:}],'%s %u %u %u %u %u');
node4_t = node1_t;
e3t = [node1_t,node2_t,node3_t,node4_t];
[~,cell_num_q,node1_q,node2_q,node3_q,node_4_q,~] = strread([s_e4q{:}],'%s %u %u %u %u %u %u');
e4q = [node1_q,node2_q,node3_q,node_4_q];
[~,~,node_X,node_Y,~] = strread([s_nd{:}],'%s %u %f %f %f');
cell_id = [cell_num_t;cell_num_q];
[~,i] = sort(cell_id,1,'ascend');
cell_node = [e3t;e4q];
cell_node = cell_node(i,:);
谢谢你的帮助。亚历克斯
5条答案
按热度按时间i2loujxw1#
当然,我会使用IOStreams。从CSV文件中阅读一个或多个同构数组而无需使用任何引号是相当简单的:
由于文件结构简单,逻辑实际上可以简化:如果自动读取分隔符,则可以将每行视为一个值序列,而不是单独阅读值。由于逗号不会被自动读取,因此在为内部行创建字符串流之前,逗号将被替换为空格。相应的代码变为
以下是发生的情况:
1.目的地
values
被定义为double
的向量的向量。没有任何东西可以保证不同行的大小相同,但是一旦读取文件,检查这一点就很简单了。std::ifstream
是用文件定义和初始化的。在构造后检查文件是否可以打开以进行阅读(if (!fin) { std::cout << "failed to open...\n";
)可能是值得的。1.文件一次处理一行。使用
std::getline()
将行读取到std::string
中。当std::getline()
失败时,它无法读取另一行,转换结束。1.读取
line
后,所有逗号都将替换为空格。1.从这样修改的
line
构造用于阅读行的字符串流。原始代码重用了一个std::istringstream
,它在循环外部声明,以保存构造流的所有时间。由于流在行完成时会变坏,因此在将其内容设置为in.str(line)
之前,首先需要对其进行in.clear()
ed。1.使用
std::istream_iterator<double>
迭代各个值,该std::istream_iterator<double>
仅从构造它的流中读取值。给定的迭代器in
是序列的开始,默认构造的迭代器是序列的结束。1.迭代器产生的值序列用于立即构造一个表示行的临时
std::vector<double>
。1.将临时向量推到目标数组的末尾。
之后的一切都只是使用C++11特性(基于范围的for和具有
auto
自动推导类型的变量)打印生成的矩阵的内容。e0uiprwp2#
正如here建议的那样,改变getline escape可能会帮助你更好地阅读csv文件,但你需要将类型从string改为int。
为了处理任何数量的行和行,您可以使用多维向量(向量内部的向量,如所述here),然后您将每行放在一个向量中,所有行都放在更大的向量中
p1tboqfb3#
这条线是错的。编译器认为你试图用
FILE*
初始化变量fclose
,这是错误的。如果你只是想关闭文件,应该是这样的:mdfafbf14#
我打算这作为一个编辑迪特马尔库尔的解决方案,但它被拒绝了太大的编辑.
将Matlab转换为C的通常原因是性能。所以我对这两种解决方案进行了基准测试。我用G 4.7.3为cygwin编译了以下选项“-Wall -Wextra -std=c++0x -O3 -fwhole-program”。我在32位Intel Atom N550上测试过。
作为输入,我使用了2个10,000行文件。第一个文件是每行10个“0.0”值,第二个文件是每行100个“0.0”值。
我在命令行中使用time计时,并使用了三次运行中user+sys的平均值。
我修改了第二个程序,像第一个程序一样从
std::cin
读取。最后,我用
std::cin.sync_with_stdio(false);
再次运行了测试结果(以秒为单位的时间):
显而易见的结论是,版本B稍微快一点,但更重要的是,您应该禁用与stdio的同步。
gblwokeq5#
下面的代码从csv文件中读取行并打印它们。