Search code examples
matlabfile-iomat-file

Matfile isn't loading the structure's field names


Background

I encountered some strange behaviour with the function "matfile" in Matlab 2016b - not sure what's going on, and I can't replicate it or create a test case.

I have a structure, which I saved to a server, like so:

PathToFile='ServerPath\My Documents\MyProj\testMatF.mat';
save(PathToFile,'-struct','myStruct'); %I tried the -v7.3 flag

Problem

Then I read it in with:

m1=matfile(PathToFile);

On other, very similar structs, I can do:

myFields=fieldnames(m1);

But for this one file I can't, all I get is the auto "Properties" field.

What I've tried

  1. myFields=who(m1) - gives me list of fieldnames... sometimes. I don't know the who function well, but it seems, if I intersperse who m1 then myFields=who(m1) it works.

  2. Explicitly typing m1.TheFieldName, works.

  3. Moving the file to a location on the comp, like C:\Data\. Then using fieldnames works.

  4. Using load, works.

Does it have to do with the server access, corrupted file, matfile properties? One other weird thing is some of my .m files in this particular folder, when I try to open them results in: Does not exist, when clearly it does, since I click on it and can use the run function with it... Additional: Windows 7. Recently updated license.

Please let me know what info you can use to help out. Either to create a new file that will work, or fix the problem with the current file. Thanks.


EDIT

Example output in my command window - seemingly incomprehensible...

m1=matfile(fullfile(projPath,'NexusMarkersProcessed.mat'),'Writable',false)

m1 =

matlab.io.MatFile

Properties: Properties.Source: '\bontempi.medicine.utorad.utoronto.ca\home\PT\zabjeklab3\My Documents\Data\Active Projects\JC_Hip\FL1502\FL1502\Patient Classification 2\NexusMarkersProcessed.mat' Properties.Writable: false

Methods

K>> m1.Properties.Source

ans =

\bontempi.medicine.utorad.utoronto.ca\home\PT\zabjeklab3\My Documents\Data\Active Projects\JC_Hip\FL1502\FL1502\Patient Classification 2\NexusMarkersProcessed.mat

K>> java.io.File(m1.Properties.Source).exists()

ans =

logical

0

Pause to paste in this window... go back:

java.io.File(m1.Properties.Source).exists()

ans =

logical

1

K>> who(m1)

Your variables are:

Patient10 Patient5 Patient9 Patient11 Patient6 Patient3
Patient7

K>> who(m1) K>> who(m1) K>> java.io.File(m1.Properties.Source).exists()

ans =

logical

0

K>>

So it sometimes finds the file, and can read it in. Othertimes it cannot - is this to do with the fact that it's on a network drive?

Any help is appreciated.


Solution

  • This issue is caused by accessing a file on a network drive. One workaround is to copy the file to a local drive (C: is used), and then use matfile, use the result as needed, then replace the network drive file, and delete the local file, to return things to their original state. Some research made me realize things are slower than they need to be if any files, even the .m ones, are on the network. Here's a function that worked:

    function [m,noData]=safeMatFile(FilePath,safeFilePath)
            %FilePath: absolute path to where the file is on the network
            %safeFilePath: absolute path to where the file will be temporarily copied locally, C://
            %safeDir='C:\Data';
            %safeFold='tempFolder12345679';
            %[~,tempDir,~]=mkdir(safeDir,safeFold);
            %safeFilePath=fullfile(safeDir,safeFold,FileName);
    
            noData=0;
            dirFile=dir(FilePath);
            if (length(dirFile) == 1) && ~(dirFile.isdir)%OR java below OR exist(forceFilePath,'file')==2
                %if there is a file, make a temp folder on the C drive
                if ~(java.io.File(safeFilePath).exists() && java.io.File(safeFilePath).isFile()) %ensure file doesn't exist, check dir too: || isempty(tempFolder) 
                    copyfile(FilePath, safeFilePath);%moves existing file to backup folder
                else
                    warning('SKIPPING (%s) - an old file of the same name was there, delete it!\n',safeFilePath);
                    return
                end
                %Load the temp local file into matlab
                m=matfile(safeFilePath,'Writable',true);
            else
                m=[];
                noData=1;
            end
        end
    

    Then do stuff with m... and at the end:

    function overwriteOldFiles()
        if (java.io.File(safeFilePath).exists() && java.io.File(safeFilePath).isFile())
            java.io.File(FilePath).delete();
            java.io.File(safeFilePath).renameTo(java.io.File(FilePath));
        end
    end
    

    and

    function deleteTempFiles()
        if (java.io.File(safeFilePath).exists() && java.io.File(safeFilePath).isFile())
            java.io.File(safeFilePath).delete();
        end
    end
    

    ... Then rmdir if necessary.

    Note, I tried different ways of checking if the file exists (I think the first is fastest and most reliable):

    dirFile=dir(FilePath); if (length(dirFile) == 1) && ~(dirFile.isdir)

    if (java.io.File(FilePath).exists() && java.io.File(FilePath).isFile())

    if exist(FilePath,'file')==2