从 csv 中读取大量存储在行中的数据

Reading large amount of data stored in lines from csv

我需要从 *.csv-file.

中读取大量数据(~10^6 个数据点)

所以 *.csv-file 可能看起来像这样:

x Header

x1,x2

y Header

y1,y2,y3, ...

z Header

z1,z2

...

现在我把每一行都读成字符串,并在每个逗号处分开。这是我的代码的样子:

index = 1;
headerLine = textscan(csvFileHandle,'%s',1,'Delimiter','\n');

while ~isempty(headerLine{1})

    dummy = textscan(csvFileHandle,'%s',1,'Delimiter','\n', ...
                'BufSize',2^31 - 1);
    rawData(index) = textscan(dummy{1}{1},'%f','Delimiter',',');
    headerLine = textscan(csvFileHandle,'%s',1,'Delimiter','\n');

    index = index + 1;
end

它正在运行,但速度很慢。大部分时间是在使用 textscan 拆分字符串时使用的。 (~95%)。 我用示例数据预先分配了 rawData,但它几乎没有带来任何速度。

有没有比我更好的阅读方式?

如果没有,是否有更快的拆分字符串的方法?

第一个建议:在遍历文件时将单行作为字符串读取,只需使用 fgetl(returns 一个很好的单字符串,所以不要对元胞数组进行操作)。

此外,您可能会考虑(如果可能)一次性读取所有内容,而不是从文件中重复读取:

output = textscan(fid, '%*s%s','Delimiter','\n');  % skips headers with *

如果文件太大以至于您无法一次完成所有操作,请尝试分块读取(例如,一次处理 1000 行,边读边解析数据)。

对于字符串的转换,有 str2numstrsplit+str2double 的选项,但我唯一能想到的可能比 [=16= 稍微快一点] 是 sscanf。由于这不接受分隔符作为单独的输入,因此将其放入格式字符串中(最后一个值不以 , 结尾,是的,但是 sscanf 可以处理)。

for n = 1:length(output);
    data{n} = sscanf(output{n},'%f,');
end

使用有限的测试数据进行的测试表明 sscanf 更快一些(但可能取决于 machine/version/data 大小)。