将十六进制数据加载到 MATLAB 时出现问题(bug?)

发布于 2024-08-06 23:05:35 字数 806 浏览 5 评论 0原文

我正在尝试使用 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

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

除了我自己重新实现文件解析之外,是否有解决该问题的方法?

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

I'm trying to load the following ascii file into MATLAB using load()

% some comment
1 0xc661
2 0xd661
3 0xe661

(This is actually a simplified file. The actual file I'm trying to load contains an undefined number of columns and an undefined number of comment lines at the beginning, which is why the load function was attractive)

For some strange reason, I obtain the following:

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

data =

         1       50785
         2       58977
         3       58977 

I've observed that the problem occurs anytime there's a "d" in the hexadecimal number.

Direct hex2dec conversion works properly:

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

importdata seems to have the same conversion issue, and so does the ImportWizard:

K>> importdata('testMixed.txt')

ans =

       1       50785
       2       58977
       3       58977

Is that a bug, am I using the load function in some prohibited way, or is there something obvious I'm overlooking?

Are there workarounds around the problem, save from reimplementing the file parsing on my own?

Edited my input file to better reflect my actual file format. I had a bit oversimplified in my original question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请持续率性 2024-08-13 23:05:35

“高尔夫”答案:

这从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 的回答<的启发/a>.

"GOLF" ANSWER:

This starts with the answer from mtrw and shortens it further:

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]).';

PREVIOUS ANSWER:

My first thought was to use TEXTSCAN, since it has an option that allows you to ignore certain lines as comments when they start with a given character (like %). However, TEXTSCAN doesn't appear to handle numbers in hexadecimal format well. Here's another option:

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

This will work for an arbitrary number of comments at the beginning of the file. The computation to get the number of columns was inspired by Jacob's answer.

苯莒 2024-08-13 23:05:35

新:

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

% 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));

New:

This is the best I could come up with. It should work for any number of comment lines and columns. You'll have to do the rest yourself if there are strings, etc.

% 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)

This works for data like this:

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

Output:

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

OLD:

Yeah, I don't think LOAD is the way to go. You could try:

a = char(importdata('testHexa.txt'));
a = hex2dec(a(:,3:end));
懷念過去 2024-08-13 23:05:35

是“最佳品种”

这是基于 gnovice 和 Jacob 的答案,对于以下文件来说

% 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

This is based on both gnovice's and Jacob's answers, and is a "best of breed"

For files like:

% this is my comment
% this is my other comment

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

(where the number of columns within the file MUST be the same, but not known ahead of time, and all comments denoted by a '%' character), the following code is fast and easy to read:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文