ucftools/matlab/@ucfmulti/ucfmulti.m

164 lines
5.6 KiB
Matlab

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