在MATLAB中读取CSV文件中的特定十六进制数据

时间:2014-06-03 18:55:57

标签: matlab

我查看了StackOverflow上的帖子,似乎找不到我要找的答案。我有一个大的CSV文件(450 MB),其十六进制数据如下所示:

63C000CF,6000002F,603000AF,6000C06F,617300EF,6C7C001F,6000009F,0%,63C000CF...

这是一个非常截断的例子,但基本上我有大约78个不同的十六进制值用逗号分隔,然后会有'0%',然后是78个十六进制值。这将持续很长时间。我一直在使用这样的文本扫描:

data = textscan(fid, '%s', 1, 'delimiter', '%');
data = textscan(data{1}{1}, '%s', 'delimiter', ',');
data = data{1};

count = size(data);

outstring = ['%', sprintf('\n')];
for idx = 1:count(1)           
    string = data{idx};
    stringSize = size(string);
    if stringSize(2) > 1
        outstring = [outstring, string, sprintf('\n')];
    end
end
fprintf(output_fid, '%s', outstring)

这允许我以一种方式格式化csv文件,我可以使用fgetl()来分析我是否正在查看我需要的数据。因为数据重复,我可以使用fseek()在再次调用fgetl()之前跳转到下一个匹配项。

我需要的是一种跳到结尾的方法。我希望能够使用类似fgetl()的东西,但只返回它遇到的第一个十六进制值。我将知道要在文件中移位多少字节。然后我需要确保我可以读取其他十六进制值。我问的可能吗?上面使用文本扫描的代码在一个90 MB的csv文件上花了太长时间,更不用说450 MB了。

1 个答案:

答案 0 :(得分:0)

Mathworks MATLAB Central Answers页面上从用户Cedric Wannaz获得的答案。

新解决方案

这是一个更有效的解决方案;我使用的是122MB文件,因此您对时间有了一个了解

% One line for reading the whole file. To perform once only.
 tic ;
 content = fileread( 'adam_1.txt' ) ;
 fprintf( 'Time for reading the file    : %.2fs\n', toc ) ;
 % One line for defining an extraction function. To perform once only.
 extract = @(label) content(bsxfun( @plus, ...
                                    strfind( content, [label,','] ).' - 6, ...
                                    0 : 5 )) ;
 % Then it is one call per label to extract data.
 tic ;
 data = extract( 'CF' ) ;
 fprintf( 'Time for extracting one label: %.2fs\n', toc ) ;

运行这个,我获得

  

阅读文件的时间:0.52s

     

提取一个标签的时间:0.62s

前战解决方案

以下是否适合您?

 % Read file content. To do once only.
 content = fileread( 'myFile.txt' ) ;
 % Define regexp-based extraction function. To do once only.
 getByLabel = @(label) regexp( content, sprintf( '\\w{6}(?=%s)', label ), ...
                               'match' ) ;
 % Get all entries for e.g. label 'CF'.
 entries_CF = getByLabel( 'CF' ) ;
 % Get all entries for e.g. label '6F'.
 entries_6F = getByLabel( '6F' ) ;

我不清楚你最终需要做些什么;如果我必须设计一个用户可以选择标签并获得相应数据的GUI,我会在初始阶段进一步处理数据,例如通过在单元格数组中按标签对它们进行分组。在我猜这种情况下,Regexp不是最有效的方法,但原则是......

 labels  = {'CF', '6F', 'AF', ..} ;
 nLabels = numel( labels ) ;
 data    = cell{ 1, nLabels ) ;
 for lId = 1 : nLabels
    data{lId} = getByLabel( labels{lId} ) ;
 end

然后当用户选择' CF' ..

 lId = strcmpi( label, labels ) ;
 dataForThisLabel = data{lId} ;