问题(错误?)将十六进制数据加载到MATLAB中

时间:2009-10-08 17:33:45

标签: matlab hex

我正在尝试使用load()

将以下ascii文件加载到MATLAB中
% some comment
1 0xc661
2 0xd661
3 0xe661

(这实际上是一个简化文件。我试图加载的实际文件包含一个未定义的列数和一个未定义数量的注释行,这就是加载函数很有吸引力的原因)

出于某些奇怪的原因,我获得了以下内容:

K>> data = load('testMixed.txt')

data =

         1       50785
         2       58977
         3       58977 

我观察到,只要十六进制数中有“d”,就会出现问题。

直接hex2dec转换正常工作:

K>> hex2dec('d661')
ans =
       54881

importdata似乎有相同的转换问题,ImportWizard也是如此:

K>> importdata('testMixed.txt')

ans =

       1       50785
       2       58977
       3       58977

这是一个错误,我是否以某种禁止的方式使用加载功能,或者是否有一些明显我忽视的东西?

是否存在解决问题的方法,除了重新实现我自己的文件解析?

编辑我的输入文件以更好地反映我的实际文件格式。我原来的问题有点过于简单了。

3 个答案:

答案 0 :(得分:3)

“GOLF”答案:

这从mtrw的答案开始,并进一步缩短:

fid = fopen('testMixed.txt','rt');
data = textscan(fid,'%s','Delimiter','\n','MultipleDelimsAsOne','1',...
                'CommentStyle','%');
fclose(fid);
data = strcat(data{1},{' '});
data = sscanf([data{:}],'%i',[sum(isspace(data{1})) inf]).';

以前的答案:

我的第一个想法是使用TEXTSCAN,因为它有一个选项,允许您在以给定字符(如%)开头时忽略某些行作为注释。但是,TEXTSCAN似乎不能很好地处理十六进制格式的数字。这是另一种选择:

fid = fopen('testMixed.txt','r');     % Open file

% First, read all the comment lines (lines that start with '%'):

comments = {};
position = 0;
nextLine = fgetl(fid);                % Read the first line
while strcmp(nextLine(1),'%')
  comments = [comments; {nextLine}];  % Collect the comments
  position = ftell(fid);              % Get the file pointer position
  nextLine = fgetl(fid);              % Read the next line
end
fseek(fid,position,-1);               % Rewind to beginning of last line read

% Read numerical data:
nCol = sum(isspace(nextLine))+1;       % Get the number of columns
data = fscanf(fid,'%i',[nCol inf]).';  % Note '%i' works for all integer formats
fclose(fid);                           % Close file

这适用于文件开头的任意数量的注释。获得列数的计算受Jacob's answer启发。

答案 1 :(得分:2)

这是我能想到的最好的。它应该适用于任意数量的注释行和列。如果有字符串等,你必须自己完成剩下的工作。

% Define the characters representing the start of the commented line
% and the delimiter
COMMENT_START = '%%';
DELIMITER = ' ';

% Open the file
fid = fopen('testMixed.txt');

% Read each line till we reach the data    
l = COMMENT_START;
while(l(1)==COMMENT_START)
    l = fgetl(fid);
end

% Compute the number of columns
cols = sum(l==DELIMITER)+1;
% Split the first line 
split_l = regexp(l,' ','split');

% Read all the data
A = textscan(fid,'%s');
% Compute the number of rows
rows = numel(A{:})/cols;

% Close the file
fclose(fid);

% Assemble all the data into a matrix of cell strings
DATA = [split_l ; reshape(A{:},[cols rows])']; %' adding this to make it pretty in SO

% Recognize each column and process accordingly
% by analyzing each element in the first row
numeric_data = zeros(size(DATA));
for i=1:cols
    str = DATA(1,i);
    % If there is no '0x' present
    if isempty(findstr(str{1},'0x')) == true
        % This is a number
        numeric_data(:,i) = str2num(char(DATA(:,i)));
    else
        % This is a hexadecimal number
        col = char(DATA(:,i));
        numeric_data(:,i) = hex2dec(col(:,3:end));
    end
end

% Display the data
format short g;
disp(numeric_data)

这适用于以下数据:

% Comment 1
% Comment 2
1.2 0xc661 10 0xa661
2 0xd661 20 0xb661
3 0xe661 30 0xc661

输出:

  1.2        50785           10        42593
    2        54881           20        46689
    3        58977           30        50785

<强> OLD:

是的,我不认为LOAD是要走的路。你可以尝试:

a = char(importdata('testHexa.txt'));
a = hex2dec(a(:,3:end));

答案 2 :(得分:2)

这是基于gnovice和雅各布的答案,并且是“最佳品种”

对于以下文件:

% this is my comment
% this is my other comment

1 0xc661 123
2 0xd661 456
% surprise comment
3 0xe661 789 
4 0xb661 1234567

(其中文件中的列数必须相同,但未提前知道,并且所有注释都由'%'字符表示),以下代码快速且易于阅读:

f = fopen('hexdata.txt', 'rt');
A = textscan(f, '%s', 'Delimiter', '\n', 'MultipleDelimsAsOne', '1', 'CollectOutput', '1', 'CommentStyle', '%');
fclose(f);
A = A{1};
data = sscanf(A{1}, '%i')';
data = repmat(data, length(A), 1);
for ctr = 2:length(A)
    data(ctr,:) = sscanf(A{ctr}, '%i')';
end