2

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.

  • When you tried all of the above things, were you saving the MAT-file with version 7 (the default, unless you changed your preferences) or were you explicitly saving with the version 7.3 flag? If you didn't keep track, re-try everything, making sure that you're explicitly saving with the version 7.3 flag and you still get the same errors. The `matfile(filename)` function assumes the `filename` refers to a version 7.3 MAT-file. If you're saving with version 7 - use `load()`; when using version 7.3 - use `matfile()` if necessary. – Vladislav Martin Feb 07 '17 at 20:20
  • Thanks Vladislav, I'll check, but the doc says `"If you index into a variable in a Version 7 (the current default) or earlier MAT-file, MATLAB® warns and temporarily loads the entire contents of the variable."`, so it would still work (if I'm interpreting that right). –  Feb 08 '17 at 16:45

1 Answers1

0

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