Since str2num and str2double are incredibly slow, I spent a while trying to speed up the code. It was taking 3 minutes to apply either of those to my cell array one time. Using the following, I was able to speed up reading a 48002 line text file with 172 columns (except for the header) from 6.5 minutes to 28 seconds.
clearvars
close all
% clc
tstart=tic;
%%Open the file and read it using textscan
%file name as string
fname = 'sample_text.txt';
%open the file as read only
fid = fopen(fname,'r');
%scan file to cell array as strings using a row delimiter of newline
%character
celltext=textscan(fid,'%s','delimiter','\n');
%close the file
fclose(fid);
%%Find the Number of Header Lines in the File
%Create a cell array of #rows x 1 with each cell containing a column vector
%of the numeric values from its row in the text file - if a row has strings, it
%will appear as empty
notnumcell=cellfun(@(s)sscanf(s,'%f'), celltext{1,1},'UniformOutput',false);
%find the logical vector corresponding to the empty rows (1 is empty, 0 is
%not)
strloc=cellfun('isempty',notnumcell);
%in each rows x 1 cell, split the string and then find the length of the
%split string (this represents the number of columns in each row of the
%data file) - convert the cell containing lengths to a column vector where
%each row contains the number of columns in that row
cellsize=cell2mat(cellfun(@length,cellfun(@strsplit,celltext{1,1},'UniformOutput',false),'UniformOutput',false));
%find max value of the columns
maxcol=max(cellsize);
%find a logical vector corresponding to rows that have the number of
%columns equal to maxcol (1 has maxcol, 0 has different # of columns)
maxcolind=cellsize==maxcol;
%the row number of the variable names and also the number of header lines
%in the file corresponds to the final line that has maxcols and is also a
%string - this returns the index number of that row
hlines=find(strloc&maxcolind,1,'last');
%%Find Parameter Names
%Use hlines to find the nested cell row from celltext that contains the
%parameter names and split the string, so that there is one cell for each
%parameter - these will be used as the field names for the structure
varnames=strsplit(celltext{1,1}{hlines,1});
% %replace '+' and '-' in varnames with 'plus' and 'minus' since those
% %characters cannot be in field names
varnames=strrep(strrep(varnames,'+','plus'),'-','minus');
%%Import Data after Headerlines as Numeric
%open the file as read only
fid = fopen(fname,'r');
%read the rest of the file after the headerlines into a cell array as
%floats and then convert to a matrix
valmat=cell2mat(textscan(fid, repmat('%f',1,maxcol),'Headerlines',hlines));
%close the file
fclose(fid);
%%Loop through the length of the variable name to construct the structure
for i1=1:length(varnames)
%use dynamic references for field names and the corresponsing column of
%values to construct the structure
s.(varnames{i1})=valmat(:,i1);
end
%%Calculate total time to run the program
tend=toc(tstart);
disp(['Total run time is ' num2str(tend) ' seconds.'])