function table = strcsvread(varargin) % Read a CSV file containing non-numeric fields (strings) and % return a cell array. Numbers are converted to double and, if contiguous, % can be easily converted to arrays with cell2mat. The remaining % are left as strings. % % Usage: % table = strcsvread(filename,delimiter,end-of-line) % % - filename = CSV file to be read % - delim = Field separator. Default = ',' % - eol = Record separator. Default = '\n' % % _____________________________________ % Anderson M. Winkler % Yale University / Institute of Living % Oct/2010 % http://brainder.org % Accept the inputs narginchk(1,3); filename = varargin{1}; if nargin == 3 delimiter = sprintf(varargin{2}); eolmark = sprintf(varargin{3}); elseif nargin == 2 delimiter = sprintf(varargin{2}); eolmark = sprintf('\n'); elseif nargin == 1 delimiter = sprintf(','); eolmark = sprintf('\n'); end % Read the whole CSV file as a single stream of data fid = fopen(filename,'r'); stream = fread(fid,Inf,'uint8=>char')'; fclose(fid); % Add an EOL at the end of the stream if not existing % This prevents an error later if stream(end) ~= eolmark stream = [stream eolmark]; end % Identify where the EOLs and delimiters are eolpos = find(stream == eolmark); delpos = find(stream == delimiter); % Allocate a provisory table (cell array) with a size estimated from % the number of delimiters and EOLs found. It grows later if needed table = cell(numel(eolpos),floor(numel(delpos)/numel(eolpos))); % Loop over each EOL get the content between each eolpos = [0 eolpos]; for r = 1:numel(eolpos)-1 rowtmp = stream(eolpos(r)+1 : eolpos(r+1)-1); % Loop over each delimiter per row and get the content between delpos = find(rowtmp == delimiter); delpos = [0 delpos numel(rowtmp)+1]; %#ok for c = 1:numel(delpos)-1 % Store in the cell array of results table{r,c} = rowtmp(delpos(c)+1 : delpos(c+1)-1); % If the content can be converted to number, do so % and deal with the NaN case if isempty(deblank(table{r,c})) || strcmpi(strtrim(table(r,c)),'NaN') table{r,c} = NaN; end testnum = str2double(table{r,c}); if ~ isnan(testnum) table{r,c} = testnum; end end end