Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions MatlabFileHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class Variable
public Type dataType;
public String name;
public object data;
public object Image;
}

internal enum MatfileVersion
Expand All @@ -27,6 +28,14 @@ internal class Tag
public object data; //In case of small data format, otherwise null
}

internal class Flag
{
public Tag Tag;
public bool Complex = false;
public bool Global = false;
public bool Logical = false;
public Type dataClass;
}
internal class Header
{
public String text;
Expand Down Expand Up @@ -102,6 +111,25 @@ public static Tag ReadTag(this BinaryReader reader)
return t;
}


public static Flag ReadFlag(this BinaryReader reader)
{
Flag f = new Flag() { Complex = false, Global = false, Logical = false };
f.Tag = reader.ReadTag();
UInt32 flagsClass = reader.ReadUInt32();
byte flags = (byte)(flagsClass >> 8);
if ((flags & 0x08) == 0x08)
f.Complex = true;
if ((flags & 0x04) == 0x04)
f.Global = true;
if ((flags & 0x02) == 0x02)
f.Logical = true;
f.dataClass = MatfileHelper.parseArrayType((byte)flagsClass);
reader.ReadUInt32();//unused flags
//Flag f = matrixStream.ReadFlag();

return f;
}
public static void AdvanceTo8ByteBoundary(this BinaryReader r)
{
long offset = (8 - (r.BaseStream.Position % 8)) % 8;
Expand Down
59 changes: 37 additions & 22 deletions MatlabFileReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@ private static void ReadMatrix(ref Variable vi, UInt32 length, BinaryReader matr

//Array flags
//Will always be too large to be in small data format, so not checking t.data
t = MatfileHelper.ReadTag(matrixStream);
UInt32 flagsClass = matrixStream.ReadUInt32();
byte flags = (byte)(flagsClass >> 8) ;
if ((flags & 0x80) == 0x80)
throw new IOException("Complex numbers not supported");
vi.dataType = MatfileHelper.parseArrayType((byte)flagsClass);
matrixStream.ReadUInt32();//unused flags
//t = MatfileHelper.ReadTag(matrixStream);
//UInt32 flagsClass = matrixStream.ReadUInt32();
//byte flags = (byte)(flagsClass >> 8) ;
//if ((flags & 0x80) == 0x08)
// throw new IOException("Complex numbers not supported");
//vi.dataType = MatfileHelper.parseArrayType((byte)flagsClass);
//matrixStream.ReadUInt32();//unused flags
Flag Flag = matrixStream.ReadFlag();
vi.dataType = Flag.dataClass;

//Dimensions - There are always 2 dimensions, so this
//tag will never be of small data format, i.e. not checking for t.data
Expand All @@ -76,7 +78,7 @@ private static void ReadMatrix(ref Variable vi, UInt32 length, BinaryReader matr
int elements = 1;
for (int i = 0; i < arrayDimensions.Length; i++)
{
int dimension = (int)matrixStream.ReadUInt32();
int dimension = (int)matrixStream.ReadUInt32();// depends on sizeof(t.dataType) => MatfileHelper.MatlabBytesPerType(t.dataType)
arrayDimensions[arrayDimensions.Length - i - 1] = dimension;
elements *= dimension;
}
Expand All @@ -102,35 +104,48 @@ private static void ReadMatrix(ref Variable vi, UInt32 length, BinaryReader matr

//Read and reshape data
t = MatfileHelper.ReadTag(matrixStream);
reshape(ref vi.data, ref vi.dataType, matrixStream, t, arrayDimensions, elements);

// Read Imaginary data
if (Flag.Complex)
{
t = matrixStream.ReadTag();
reshape(ref vi.Image, ref vi.dataType, matrixStream, t, arrayDimensions, elements);
}
//Move on in case the data didn't end on a 64 byte boundary
matrixStream.BaseStream.Seek(offset + length, SeekOrigin.Begin);
}

private static void reshape(ref object data, ref Type dataType, BinaryReader matrixStream, Tag t, int[] arrayDimensions, int elements)
{
if (t.length / MatfileHelper.MatlabBytesPerType(t.dataType) != elements)
throw new IOException("Read dimensions didn't correspond to header dimensions");

Array readBytes;
if (t.data == null)
readBytes = MatfileHelper.CastToMatlabType(vi.dataType, matrixStream.ReadBytes((int)t.length));
readBytes = MatfileHelper.CastToMatlabType(t.dataType, matrixStream.ReadBytes((int)t.length));
else
readBytes = (Array)t.data;

Array reshapedData = Array.CreateInstance(vi.dataType, arrayDimensions);
if (t.dataType != vi.dataType) //This happens when matlab choses to store the data in a smaller datatype when the values permit it
Array reshapedData = Array.CreateInstance(dataType, elements);//elements variable replaced with arrayDimensions to sure Linear data
if (t.dataType != dataType) //This happens when matlab choses to store the data in a smaller datatype when the values permit it
{
Array linearData = Array.CreateInstance(vi.dataType, readBytes.Length);
Array linearData = Array.CreateInstance(dataType, readBytes.Length);
Array.Copy(readBytes, linearData, readBytes.Length);
Buffer.BlockCopy(linearData, 0, reshapedData, 0, linearData.Length * MatfileHelper.MatlabBytesPerType(vi.dataType));
vi.dataType = t.dataType;
Buffer.BlockCopy(linearData, 0, reshapedData, 0, linearData.Length * MatfileHelper.MatlabBytesPerType(dataType));
// dataType = t.dataType;
}
else //Readbytes is already in the correct type
Buffer.BlockCopy(readBytes, 0, reshapedData, 0, readBytes.Length * MatfileHelper.MatlabBytesPerType(vi.dataType));
Buffer.BlockCopy(readBytes, 0, reshapedData, 0, readBytes.Length * MatfileHelper.MatlabBytesPerType(dataType));

if(reshapedData.Length == 1)
vi.data = reshapedData.GetValue(0);
if (reshapedData.Length == 1)
data = reshapedData.GetValue(0);
else
vi.data = reshapedData;
data = reshapedData;

//Move on in case the data didn't end on a 64 byte boundary
matrixStream.BaseStream.Seek(offset + length, SeekOrigin.Begin);
}

public void Close()
{
readStream.Close();
Expand Down