www.gusucode.com > datastoreio工具箱 matlab源码程序 > datastoreio/+matlab/+io/+datastore/+splitreader/TextFileSplitReader.m

    classdef TextFileSplitReader < matlab.io.datastore.splitreader.SplitReader
%TextFileSplitReader   SplitReader for reading text file splits.
%   Allows the user to ensure the reader returns data ending at logical 
%   record boundaries as defined by the end of record (EOR) character 
%   sequence. Once can customize the size of the chunk that is returned by
%   this reader and the EOR sequence. This reader is assigned a split and
%   iterates through the split using the hasNext and getNext
%   paradigm. It keeps doing this until it runs out of data.

%   Copyright 2015 The MathWorks, Inc.

    properties
        Split; 
    end
    
    properties (Transient, Access = 'private')
        SizeRead = 0;       % size currently read from the split
        Stream;             % the stream to use for reading
    end
    
    properties (Transient)
        FileEncoding;       % encoding to use
        EOR;                % end of record to use
    end

    methods 
        function set.EOR(rdr, eor)
            rdr.EOR = sprintf(eor);
        end
    end
    
    methods        
        function rdr = TextFileSplitReader()
            % split property must be initialized before use
            rdr.Split = [];
            rdr.Stream = [];
        end
        
        function tf = hasNext(rdr)
            % Return logical scalar indicating availability of data
            tf = ~isempty(rdr.Split) && rdr.SizeRead < rdr.Split.Size;
        end
        
        function [data, info] = getNext(rdr)
            % Return "data" and "info" read while iterating over the split
            
            % local vars
            split = rdr.Split;
            if rdr.SizeRead < split.Size
                remainingSize = split.Size-rdr.SizeRead;
                [splitBody, numBytes] = readTextBytes(rdr.Stream, remainingSize);
                [splitEnd, numEndBytes] = readUpto(rdr.Stream, rdr.EOR);
                data = [splitBody, splitEnd];
            else
                data = '';
                numBytes = 0;
                numEndBytes = 0;
            end

            % populate the info struct
            info = struct('Filename', split.Filename, ...
                          'FileSize', split.FileSize, ...
                          'Offset', split.Offset + rdr.SizeRead, ...
                          'NumCharactersRead', numel(data));

            % update the size read, add numel in splitEnd as we read
            % that many chars, and therefore at least that many bytes
            rdr.SizeRead = rdr.SizeRead + numBytes + numEndBytes;
        end

        function reset(rdr)
            try
                % any errors in initializing the stream must restore
                % SizeRead as that determines if a split has data.
                initStream(rdr);
                
                rdr.SizeRead = 0;
                
                if ~isempty(rdr.Split) && (rdr.Split.Offset ~= 0)
                    % if the split does not start at 0, we must skip up to
                    % its start point, as channels by default are at
                    % position 0
                    rdr.SizeRead = skipBytes(rdr.Stream, rdr.Split.Offset) - ...
                                                          rdr.Split.Offset;
                    % we then skip the first record we see
                    [~,numBytes] = readUpto(rdr.Stream, rdr.EOR);
                    rdr.SizeRead = rdr.SizeRead + numBytes;
                end
            catch ME                
                % throw the pathlookup ID as stream ID has IRI information
                if strcmp(ME.identifier, ...
                    'MATLAB:datastoreio:stream:fileNotFound')
                    error(message('MATLAB:datastoreio:pathlookup:fileNotFound', ...
                                                      rdr.Split.Filename));
                end                
                throw(ME);
            end
        end
        
        function frac = progress(rdr)
        % Percentage of read completion between 0.0 and 1.0 for the split.
            frac = min(rdr.SizeRead/rdr.Split.Size, 1.0);
        end
        
        function delete(rdr)
        % Delete the reader
            rdr.Stream = [];
        end

    end
    
    methods (Access = 'protected')
        function rdrCopy = copyElement(rdr)
           % make a shallow copy of all properties
           rdrCopy = copyElement@matlab.mixin.Copyable(rdr);
           % unshare the shallow copy to the handle of the stream
           rdrCopy.Stream = [];
           if ~isempty(rdrCopy.Split)
               rdrCopy.initStream();
               rdrCopy.Stream.seek(rdrCopy.Split.Offset + rdrCopy.SizeRead);
           end
        end 
    end
    
    methods (Access = 'private')

        function initStream(rdr)
            import matlab.io.datastore.internal.filesys.createStream;
            
            split = rdr.Split;
            if isempty(split)
                return;
            end

            rdr.Stream = createStream(split.Filename,'rt', rdr.FileEncoding);
        end
        
    end
end