function argout = readascii(argin)
% Reads ASCII Files
%
% USAGE:
% argout = readascii(argin)
%
% DESCRIPTION:
% Reads an ascii file and returns (if nargout==1)
% a structure with several fields including the
% headers, text and nuemrica data.
% If the name for an out-file is given,
% the file is changed for MatLab load
% compatibility commenting all "text" lines and
% inserting NaN'. The out file may be saved as
% binary, which only saves the data of the in-file.
%
% INPUT VARIABLE:
% argin is a structure array with fields:
% infile = file to be read
% outfile = name of out-file (only if given)
% outperm = permision for out file used for fopen.m
% examples - 'w', 'wb', 'a+', etc
% default - 'w'
% outprec = precision for out file used for fwrite.m
% examples - 'uchar', 'int8', 'single', 'double'
% default - 'uchar'
% old = text or numbers that want to be replaced
% If more than one number or text needs to be
% replaced, old may be given as a cell array
% examples - -9999, {'0000','-----'}
% default - '*****'
% new = text or number that replaces old
% default - 'NaN'
%
% OUTPUT VARIABLE:
% argout is a structure array with the same fields as argin, plus:
% header(s) = heading of file and/or any row with characters other
% than e that are commented in an ascii out file
% any line starting with % or any non alphabet characters
% text = string data in file
% data = vector or matrix with data read from file
% flag = text indicating whether all data was read,
% if there exist rows with different
% number of columns in the in file, and
% the amount of data written to a binary file
%
% NOTES:
% Using outfile == infile is valid but slows
% the program down considerably.
% The uigetfile dialog is invoked if nargin==0.
% Commenting a linea twice or any data linea with NaN' is avoided.
% Only permits writing to binary file if the ascii file contains
% only one data size
%
%Copy-Left, Alejandro Sanchez
if nargin==0
[file,fpath]=uigetfile('*.*','Select In-File:');
if ~any(file), return, end
argin.infile=[fpath,file];
end %if
if nargin==1 && ~isstruct(argin)
argin.infile=argin;
end
finid=fopen(argin.infile,'r');
if finid < 0
error(['Could not open file: ',argin.infile])
end
if nargin==0
disp('--------------- IN-FILE --------------------------')
type(argin.infile)
disp('----------------- READASCII ------------------------')
quest = input('Do you want to write the data read to a file? (Yes=1,No~=1)\n');
if isempty(quest)
quest = 0;
end
if quest==1
[filename,filepath]=uiputfile('*.*','Save data as');
argin.outfile = [filepath,filename];
end
quest = input('Do you want to replace something in the file? (Yes=1,No~=1)\n');
if isempty(quest)
quest = 0;
end
if quest==1
% argin.old = inputdlg({strvcat('Enter the text you want to',...
% 'replace. e.g. 9999, port'),'','',''},...
% 'readascii.m');
disp('Enter want you want to change as a cell')
argin.old = eval(input('e.g. {''NaN'', ''Port''} \n',''));
end
if isfield(argin,'old')
for k=length(argin.old):-1:1
if isempty(argin.old{k})
argin.old{k} = [];
else
break
end
end
end
end
if ~isfield(argin,'old')
old{1} = '*****';
elseif ischar(argin.old)
old{1} = argin.old;
elseif isnumeric(argin.old)
for k=1:length(argin.old)
old{k} = num2str(argin.old(k));
end %for
elseif iscell(argin.old)
old = argin.old;
for k=1:length(old)
if isnumeric(old{k})
old{k} = num2str(old{k});
end %if
end %for
end
Nold = length(old);
if ~isfield(argin,'new')
new{1} = 'NaN';
end
if isnumeric(new)
new{1} = num2str(new);
elseif iscell(new)
Nnew = length(new);
for k=1:Nold
if k>Nnew
new{k} = new{k-1};
end
if isnumeric(new{k})
new{k} = num2str(new{k});
end
end %for
end
exout = isfield(argin,'outfile');
if exout
if ~isfield(argin,'outperm')
argin.outperm='w';
end %if
if ~isfield(argin,'outprec')
argin.outprec='uchar';
end %if
isasc = strcmpi(argin.outprec,'uchar');
if strcmp(argin.outfile,argin.infile)
argin.outfile = 'readfile.tmp';
end %if
foutid=fopen(argin.outfile,argin.outperm);
if foutid < 0
fclose(finid);
error(['Could not open file: ',argin.outfile])
end %if
end %if
h = cell(1); %headers
s = h; %strings
d = h; %numeric data
e = 1; %counter for data
g = e; %counter for headers
j = e;%counter for string data
c = e; %flag to indicate type of data of previous line
%c=0 -> header
%c=1 -> numeric data
%c=2 -> text
flag = [];
while 1
linea = fgetl(finid);
if ~ischar(linea), break, end
linep = linea;
if ~isempty(linea) %skip
%Replaces old with new in all of file
for j=1:Nold
linea = strrep(linea,old{j},new{j});
end %for
%Communly used for dates
%These are replaced by default
linea = strrep(linea,'/',' ');
linea = strrep(linea,':',' ');
linea = strrep(linea,'"',' ');
%Check if it can be converted into a number
try
nline = eval(['[',linea,']']);
catch
nline = [];
end
%if nline is empty than the linea is a string
if ~isempty(nline)
%Check if it is not the same number
%of columns as the previous data set than
%a new data set is made
if isempty(d{e})
d{e} = nline;
s2 = size(d{e},2);
elseif s2==size(nline,2) && c==1
d{e} = [d{e}; nline];
else
e = e + 1;
d{e} = nline;
s2 = size(nline,2);
if exout
flag='Warning: Posible Data Set with Irregular Number of Columns';
end %if
end
c = 1;
%If the linea is a string
else
%deblank and change to upper case
LINEA = upper(linea(~isspace(linea)));
if (LINEA(1)<'A') || (LINEA(1)>'Z')
if isempty(h{g})
h{g} = linep;
elseif c==0
h{g} = char(h{g},linep);
else
g = g + 1;
h{g} = linep;
end
c = 0;
else
if isempty(s{j})
s{j} = linep;
elseif c==2
s{j} = char(s{j},linep);
else
j = j + 1;
s{j} = linep;
end
c = 2;
end %if
%Avoids commenting twice
if ~isequal(LINEA(1),'%') && exout
linea = ['% ',linep];
end %if
end %if
if exout && isasc
fwrite(foutid,linea);
end %if
end %if
end %for
if isempty(flag)
flag = 'All data Read';
end
if exout && ~isasc
dw = fwrite(foutid,d{1},argin.outprec);
flag = [flag,' && ',num2str(dw),...
' (',num2str(size(d,1)),...
'x',num2str(size(d,2)),') Written'];
end
fclose(finid);
if isfield(argin,'outfile')
fclose(foutid);
if strcmp(argin.outfile,'readfile.tmp')
copyfile(argin.outfile,argin.infile);
delete('readfile.tmp')
end
end
if (nargout==1) || (nargin==0)
argout = argin;
if length(h)==1
argout.headers = h{1};
else
argout.headers = h;
end
if length(s)==1
argout.text = s{1};
else
argout.text = s;
end
if length(d)==1
argout.data = d{1};
else
argout.data = d;
end
argout.flag = flag;
end
return