0

I have a set of data in the following format, and I would like to import each block in order to analyze them with Matlab.

                        Emax=0.5/real

----------------------------------------------------------------------

           4.9750557                           14535
           4.9825821                           14522
            4.990109                           14511
           4.9976354                           14491
           5.0051618                           14481
           5.0126886                           14468
            5.020215                           14437
           5.0277414                           14418
           5.0352678                           14400
           5.0427947                           14372
           5.0503211                           14355
           5.0578475                           14339
           5.0653744                           14321

                        Emax=1/real

----------------------------------------------------------------------
           24.965595                          597544
           24.973122                          597543
           24.980648                          597543
           24.988174                          597542
           24.995703                          597542
           25.003229                          597542

I have modified this piece of code from MathWorks, but I think, I have problems dealing with the spaces between each column.

Each block of data consist of 3874 rows and is divided by a text (Emax=XX/real) and a line of ----, unfortunately is the only way the software export the data.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
G4uss
  • 3
  • 1

2 Answers2

0

This should work. I don't think textscan() will work with a file like this because of the breaks between blocks.

Essentially what this code does is loop through lines between blocks until it finds a line that matches the data format. The code is naive and assumes that the file will have exactly the number of blocks lines per block that you specify. If there were a fixed number of lines between blocks it would be a lot easier and you could remove the first inner loop and replace with just ~=fgets(fid) once for each line.

function block_data = readfile(in_file_name)

fid = fopen(in_file_name, 'r');

delimiter = ' ';
line_format = '%f %f';
n_cols = 2;            % Number of numbers per line
block_length = 3874;   % Number of lines per block
n_blocks = 2;          % Total number of blocks in file

tline = fgets(fid);
line_data = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
block_n = 0;
block_data = zeros(n_blocks,block_length,n_cols);
while ischar(tline) && block_n < n_blocks

  block_n = block_n+1;

  tline = fgets(fid);
  if ischar(tline)
    line_data = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
  end
  while ischar(tline) && isempty(line_data)
    tline = fgets(fid);
    line_data = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
  end

  line_n = 1;
  while line_n <= block_length
    block_data(block_n,line_n,:) = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
    tline = fgets(fid);
    line_n = line_n+1;
  end
end

fclose(fid)
K A
  • 187
  • 8
0

Here is one way to import the data:

% read file as a cell-array of lines
fid = fopen('file.dat', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
C = C{1};
fclose(fid);

% remove separator lines
C(strncmp('---',C,3)) = [];

% location of section headers
headInd = [find(strncmp('Emax=', C, length('Emax='))) ; numel(C)+1];

% extract each section
num = numel(headInd)-1;
blocks = struct('header',cell(num,1), 'data',cell(num,1));
for i=1:num
    % section header
    blocks(i).header = C{headInd(i)};

    % data
    X = regexp(C(headInd(i)+1:headInd(i+1)-1), '\s+', 'split');
    blocks(i).data = str2double(vertcat(X{:}));
end

The result is a structure array containing the data from each block:

>> blocks
blocks = 
2x1 struct array with fields:
    header
    data

>> blocks(2)
ans = 
    header: 'Emax=1/real'
      data: [6x2 double]

>> blocks(2).data(:,1)
ans =
   24.9656
   24.9731
   24.9806
   24.9882
   24.9957
   25.0032
Amro
  • 123,847
  • 25
  • 243
  • 454