Main Content

matlab.io.Datastore 类

命名空间: matlab.io

基础数据存储类

描述

matlab.io.Datastore 是用于创建自定义数据存储的抽象类。数据存储有助于对大型数据集进行迭代式访问,尤其是当数据太大而无法完全放入内存时。Datastore 抽象类可以声明和捕获 MATLAB® 中所有自定义数据存储所需要的接口。请使用以下语法派生您的类:

classdef MyDatastore < matlab.io.Datastore
    ...
end

要实现您的自定义数据存储,可以:

  • matlab.io.Datastore 类继承

  • 定义四个必需的方法:hasdatareadresetprogress

有关创建自定义数据存储的详细信息和步骤,请参阅Develop Custom Datastore

方法

read

从数据存储中读取数据。

[data,info] = read(ds)

data 输出可以是任何数据类型,而且必须可以垂直串联。最佳做法是以结构体形式返回 info 输出。

输出 data 的数据类型决定 tall 函数输出的数据类型。

Access: Public, Abstract: true

hasdata

确定是否有数据可读取。输出的类型为逻辑值。

tf = hasdata(ds)

Access: Public, Abstract: true

reset

在读取任何数据之前将数据存储重置为初始状态。

reset(ds)

Access: Public, Abstract: true

progress

确定已读取多少数据。

输出是介于 01 之间的双精度标量。返回值 0.55 表示已读取 55% 的数据。

p = progress(ds)

Access: Public, Abstract: true, Hidden:true

preview

返回数据的子集。

data = preview(ds)

默认实现返回前八行数据。输出的数据类型与 read 的输出相同。

preview 方法的默认实现未针对 tall 数组构造进行优化。要改善 tall 数组的性能,请根据您的数据优化实现。

Access: Public

readall

读取数据存储中的所有数据。

data = readall(ds)

输出的数据类型与 read 的输出相同。如果数据不能完全放入内存,readall 将返回错误。

readall 方法的默认实现未针对 tall 数组构造进行优化。要改善 tall 数组的性能,请根据您的数据优化实现。

Access: Public

combine

合并来自多个数据存储的数据。

dsnew = combine(ds1,ds2,...,dsN)

输出 dsnew 是具有合并数据的新数据存储,以 CombinedDatastore 对象形式返回。使用 ReadOrder="sequential" 名称-值参量返回按顺序读取数据的 SequentialDatastore 对象。

Access: Public

transform

变换数据存储。

dsnew = transform(ds,@fcn)

输出 dsnew 是具有变换后的数据的新数据存储,以 TransformedDatastore 对象形式返回。

Access: Public

isPartitionable

确定数据存储是否可分区。输出的类型为逻辑值。

tf = isPartitionable(ds)

Access: Public

isSubsettable

确定数据存储是否可取子集。输出的类型为逻辑值。

tf = isSubsettable(ds)

Access: Public

isShuffleable

确定数据存储是否可乱序。输出的类型为逻辑值。

tf = isShuffleable(ds)

Access: Public

属性

要为自定义数据存储添加句柄属性,您必须实现 copyElement 方法。例如,如果您使用 DsFileSet 对象作为自定义数据存储中的属性,则必须实现 copyElement 方法。实现 copyElement 方法可以创建数据存储对象的深拷贝。有关详细信息,请参阅Customize Copy Operation。有关 copyElement 方法的示例实现,请参阅Develop Custom Datastore

属性

Sealedfalse

有关类属性的信息,请参阅类属性

示例

全部折叠

构建一个数据存储,以便将您的自定义或专有数据载入 MATLAB® 进行串行处理。

创建一个 .m 类定义文件,其中包含实现自定义数据存储的代码。您必须将此文件保存在工作文件夹或 MATLAB® 路径上的文件夹中。.m 文件的名称必须与对象构造函数的名称相同。例如,如果您希望构造函数的名称为 MyDatastore,则 .m 文件的名称必须为 MyDatastore.m.m 类定义文件必须包含以下步骤:

  • 步骤 1:从数据存储类继承。

  • 步骤 2:定义构造函数和必需的方法。

  • 步骤 3:定义您的自定义文件读取函数。

除这些步骤之外,还需要定义处理和分析数据所需的所有其他属性或方法。

%% STEP 1: INHERIT FROM DATASTORE CLASSES
classdef MyDatastore < matlab.io.Datastore
    
    properties(Access = private)
        CurrentFileIndex double
        FileSet matlab.io.datastore.DsFileSet
    end
    
    % Property to support saving, loading, and processing of
    % datastore on different file system machines or clusters.
    % In addition, define the methods get.AlternateFileSystemRoots()
    % and set.AlternateFileSystemRoots() in the methods section. 
    properties(Dependent)
        AlternateFileSystemRoots
    end
    
    
%% STEP 2: DEFINE THE CONSTRUCTOR AND THE REQUIRED METHODS
    methods
        % Define your datastore constructor
        function myds = MyDatastore(location,altRoots)
            myds.FileSet = matlab.io.datastore.DsFileSet(location,...
                'FileExtensions','.bin', ...
                'FileSplitSize',8*1024);
            myds.CurrentFileIndex = 1;
             
            if nargin == 2
                 myds.AlternateFileSystemRoots = altRoots;
            end
            
            reset(myds);
        end
        
        % Define the hasdata method
        function tf = hasdata(myds)
            % Return true if more data is available
            tf = hasfile(myds.FileSet);
        end
        
        % Define the read method
        function [data,info] = read(myds)
            % Read data and information about the extracted data
            % See also: MyFileReader()
            if ~hasdata(myds)
                error(sprintf(['No more data to read.\nUse the reset ',... 
                     'method to reset the datastore to the start of ' ,...
                     'the data. \nBefore calling the read method, ',...
                     'check if data is available to read ',...
                     'by using the hasdata method.'])) 
            end
            
            fileInfoTbl = nextfile(myds.FileSet);
            data = MyFileReader(fileInfoTbl);
            info.Size = size(data);
            info.FileName = fileInfoTbl.FileName;
            info.Offset = fileInfoTbl.Offset;
            
            % Update CurrentFileIndex for tracking progress
            if fileInfoTbl.Offset + fileInfoTbl.SplitSize >= ...
                    fileInfoTbl.FileSize
                myds.CurrentFileIndex = myds.CurrentFileIndex + 1 ;
            end
        end
        
        % Define the reset method
        function reset(myds)
            % Reset to the start of the data
            reset(myds.FileSet);
            myds.CurrentFileIndex = 1;
        end

        % Getter for AlternateFileSystemRoots property
        function altRoots = get.AlternateFileSystemRoots(myds)
            altRoots = myds.FileSet.AlternateFileSystemRoots;
        end

        % Setter for AlternateFileSystemRoots property
        function set.AlternateFileSystemRoots(myds,altRoots)
            try
              % The DsFileSet object manages the AlternateFileSystemRoots
              % for your datastore
              myds.FileSet.AlternateFileSystemRoots = altRoots;

              % Reset the datastore
              reset(myds);  
            catch ME
              throw(ME);
            end
        end
    end
    
    methods (Hidden = true)          
        % Define the progress method
        function frac = progress(myds)
            % Determine percentage of data read from datastore
            if hasdata(myds) 
               frac = (myds.CurrentFileIndex-1)/...
                             myds.FileSet.NumFiles; 
            else 
               frac = 1;  
            end 
        end
    end
    
    methods(Access = protected)
        % If you use the  FileSet property in the datastore,
        % then you must define the copyElement method. The
        % copyElement method allows methods such as readall
        % and preview to remain stateless 
        function dscopy = copyElement(ds)
            dscopy = copyElement@matlab.mixin.Copyable(ds);
            dscopy.FileSet = copy(ds.FileSet);
        end
                
    end
end

%% STEP 3: IMPLEMENT YOUR CUSTOM FILE READING FUNCTION
function data = MyFileReader(fileInfoTbl)
% create a reader object using FileName
reader = matlab.io.datastore.DsFileReader(fileInfoTbl.FileName);

% seek to the offset
seek(reader,fileInfoTbl.Offset,'Origin','start-of-file');

% read fileInfoTbl.SplitSize amount of data
data = read(reader,fileInfoTbl.SplitSize);

end

您的自定义数据存储现在已准备就绪。使用 MyDatastore 创建一个数据存储对象,以读取您的二进制数据文件。

使用自定义数据存储预览您的专有数据并将数据读取到 MATLAB 中进行串行处理。

此示例使用简单的数据集来说明使用自定义数据存储的工作流。该数据集是由 15 个二进制 (.bin) 文件构成的集合,其中每个文件包含一列(1 个变量)和 10000 行无符号整数(10000 条记录)。

dir('*.bin')
binary_data01.bin  binary_data02.bin  binary_data03.bin  binary_data04.bin  binary_data05.bin  binary_data06.bin  binary_data07.bin  binary_data08.bin  binary_data09.bin  binary_data10.bin  binary_data11.bin  binary_data12.bin  binary_data13.bin  binary_data14.bin  binary_data15.bin  

使用 MyDatastore 函数创建一个数据存储对象。有关 MyDatastore 的实现详细信息,请参阅示例构建数据存储以读取二进制文件

folder = fullfile('*.bin'); 
ds = MyDatastore(folder); 

预览数据存储中的数据。

preview(ds)
ans = 8x1 uint8 column vector

   113
   180
   251
    91
    29
    66
   254
   214

while 循环中读取数据,并使用 hasdata 方法检查是否还有数据可供读取。

while hasdata(ds)
    data = read(ds);
    % do something
end

将数据存储重置为初始状态,并从数据存储的开头读取数据。

reset(ds);
data = read(ds);

或者,如果数据集能够完全放入内存,则读取数据存储中的所有数据。由于文件夹中包含 15 个文件,每个文件包含 10000 条记录,所以输出的大小应为 150000 条记录。

dataAll = readall(ds);
whos dataAll
  Name              Size             Bytes  Class    Attributes

  dataAll      150000x1             150000  uint8              

创建自定义数据存储对象,将其保存在 Windows® 计算机上,然后在 Linux® 计算机上加载并处理它。

在创建和保存自定义数据存储之前,请确定不同平台上数据的根路径。根路径因计算机或文件系统而不同。例如,如果您使用以下根路径访问数据:

  • 本地 Windows 计算机上的 "Z:\DataSet"

  • Linux 集群上的 "/nfs-bldg001/DataSet"

请使用 AlternateFileSystemRoots 属性关联这些根路径。有关 MyDatastore 的实现细节,请参阅示例Build Datastore to Read Binary Files

altRoots = ["Z:\DataSet","/nfs-bldg001/DataSet"];
ds = MyDatastore('Z:\DataSet\*.bin',altRoots);

检查数据存储中的文件。

fileTbl = resolve(ds.Fileset);
fileTbl.FileName
ans =

  12×1 cell array

    {'Z:\DataSet\binary_data01.bin'}
    {'Z:\DataSet\binary_data02.bin'}
    {'Z:\DataSet\binary_data03.bin'}
      .
      . 
      .

保存数据存储。

save ds_saved_on_Windows.mat ds

将数据存储加载到 Linux 平台上并检查数据存储中的文件。由于加载时在 Linux 集群上不能访问根路径 'Z:\DataSet',因此数据存储函数会根据 AlternateFileSystemRoots 属性中指定的值自动更新根路径。

load ds_saved_on_Windows.mat
fileTbl = resolve(ds.Fileset);
fileTbl.FileName
ans =

  12×1 cell array

    {'/nfs-bldg001/DataSet/binary_data01.bin'}
    {'/nfs-bldg001/DataSet/binary_data02.bin'}
    {'/nfs-bldg001/DataSet/binary_data03.bin'}
      .
      . 
      .
您现在可以在 Linux 计算机上处理和分析此数据存储。

版本历史记录

在 R2017b 中推出