Проблема (ошибка?) Загрузки шестнадцатеричных данных в MATLAB - PullRequest
1 голос
/ 08 октября 2009

Я пытаюсь загрузить следующий файл ascii в MATLAB с помощью load ()

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

3 голосов
/ 08 октября 2009

"ГОЛЬФ" ОТВЕТ:

Это начинается с ответа от 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

Это будет работать для произвольного количества комментариев в начале файла. Вычисление количества столбцов было основано на ответе Джейкоба .

2 голосов
/ 08 октября 2009

Это основано на ответах Гновице и Джейкоба и является «лучшим в своем роде»

Для таких файлов, как:

% 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
2 голосов
/ 08 октября 2009

Новое:

Это лучшее, что я мог придумать. Это должно работать для любого количества строк комментариев и столбцов. Все остальное придется делать самому, если есть строки и т. Д.

% 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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...