classdef ucfmulti < handle % High-level class to treat a directory with UCF files similarly to UCFtar files properties (Access = public) Directory % directory name Seq % sequence number IOMode % file opened in read-only or read-write mode? NumberOfSubfiles % number of subfiles end properties (Access = private) % File info fileID ioflag subFile subFileAlias subFileSize scanBuffSize = 2^17; % buffer size of scanner (max. number of files in tar) end %% ------------------------------------------------------------------------%% %% CONSTRUCORS/DESTRUCTORS %% %% ------------------------------------------------------------------------%% methods(Access=public) function obj = ucfmulti() % obj = ucf() % Default contructor obj.resetPublicProperties(); obj.resetPrivateProperties(); end function delete(obj) % obj.delete() % Default destructor obj.close(); end end %% ------------------------------------------------------------------------%% %% INITIALIZATION METHODS %% %% ------------------------------------------------------------------------%% methods(Access=public) function open(obj,directory,iseq) % obj.open(file) % Opens a file in read-only mode tmp = what(directory); % get absoulte path obj.Directory = tmp.path; obj.Seq = iseq; obj.IOMode = 'read'; obj.ioflag = 'r'; if ~exist(directory,'dir') error('Unable to open directory: %s',obj.Directory); end obj.scanDirectory(); end end %% ------------------------------------------------------------------------%% %% PUBLIC METHODS %% %% ------------------------------------------------------------------------%% methods(Access=public) function close(obj) % obj.close() % Closes a file if obj.fileID<0 return; end status = fclose(obj.fileID); if status<0 warning('Unable to close file (exit code: %d)',status); return; end obj.resetPublicProperties(); obj.resetPrivateProperties(); obj.fileID = -1; end function [ptr] = pointer(obj,fname) % [ptr] = obj.pointer(fname) % Returns a 'pointer' to the requested file within the tar-ball % which can be used to read the data without extracting. % Input % fname file name of subfile within tar-ball % Output % ptr pointer: [fid,first byte,number of bytes] if obj.fileID>=0 fclose(obj.fileID); end idx = obj.findSubfile(fname); filepath = sprintf('%s/%s',obj.Directory,obj.subFile{idx}); obj.fileID = fopen(filepath,obj.ioflag); ptr = [obj.fileID,0,obj.subFileSize(idx)]; end function [fname,fsize] = list(obj) % [fname,fsize] = obj.list() % Returns a list of name/size of all subfiles within the tar-ball % Output % fname cell array with filenames % fsize array with file sizes in bytes fname = obj.subFileAlias; fsize = obj.subFileSize; end function [flag] = isSubfile(obj,fname) % [flag] = obj.isSubfile(fname) % Checks if a subfile exists within tar-ball. % Input % fname name of subfile flag = any(ismember(obj.subFileAlias,fname)); end end %% ------------------------------------------------------------------------%% %% PRIVATE METHODS %% %% ------------------------------------------------------------------------%% methods(Access=private) function scanDirectory(obj) % obj.scanArchive() % Scans the directory for subfiles and stores meta-data in class variables. obj.subFile = cell(obj.scanBuffSize,1); obj.subFileSize = zeros(obj.scanBuffSize,1); tmp = dir(obj.Directory); strseq = sprintf('_%04d.',obj.Seq); ii = 0; for itmp=1:numel(tmp) if tmp(itmp).isdir || isempty(strfind(tmp(itmp).name,strseq)) continue; end ii = ii+1; obj.subFile{ii} = tmp(itmp).name; obj.subFileSize(ii) = tmp(itmp).bytes; obj.subFileAlias{ii} = strrep(tmp(itmp).name,strseq,'.'); end % Truncate preallocated arrays obj.NumberOfSubfiles = ii; obj.subFile = obj.subFile(1:ii); obj.subFileAlias= obj.subFileAlias(1:ii); obj.subFileSize = obj.subFileSize(1:ii); if obj.NumberOfSubfiles>obj.scanBuffSize warning('Number of subfiles exceeds scanBuffSize.'); end end function [idx] = findSubfile(obj,fname) % [idx] = obj.findSubfile(fname) % Get index of requested subfile % Input % fname name of subfile % Output % idx index of subfile isReqFile = ismember(obj.subFileAlias,fname); switch sum(isReqFile) case 0; error('File not found: %s',fname); case 1; otherwise; warning('More than one matching file found.'); end idx = find(isReqFile); end function resetPublicProperties(obj) obj.Directory = []; obj.Seq = []; obj.IOMode = []; obj.NumberOfSubfiles = []; end function resetPrivateProperties(obj) obj.ioflag = []; obj.subFile = []; obj.subFileAlias= []; obj.subFileSize = []; end end end