Example #1
0
        private void ReadVariables()
        {
            Variables = new Dictionary <string, Variable>();
            while (readStream.BaseStream.Position < readStream.BaseStream.Length)
            {
                Variable v = new Variable();

                Tag t = MatfileHelper.ReadTag(readStream);
                if (t.dataType == null)
                {
                    throw new Exception("Not an array, don't know what to do with this stuff");
                }
                else if (t.dataType.Equals(typeof(Array))) //We use Array to indicate MiMatrix
                {
                    ReadMatrix(ref v, t.length, readStream);
                }
                else if (t.dataType.Equals(typeof(ZlibStream)))
                {
                    byte[]       compressed   = readStream.ReadBytes((int)t.length);
                    byte[]       decompressed = ZlibStream.UncompressBuffer(compressed);
                    MemoryStream m            = new MemoryStream(decompressed);
                    BinaryReader br           = new BinaryReader(m);
                    Tag          ct           = MatfileHelper.ReadTag(br);
                    ReadMatrix(ref v, ct.length, br);
                }
                else
                {
                    throw new Exception("Not an array, don't know what to do with this stuff");
                }

                Variables.Add(v.name, v);
            }
        }
        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);
        }
Example #3
0
        private void WriteDataHeader(Type t)
        {
            //type of contents
            writeStream.Write(MatfileHelper.MatlabArrayTypeNumber(t));

            //store position, so we can later overwrite this placeholder
            dataLengthStartPosition = writeStream.BaseStream.Position;

            //add placeholder for size
            for (int i = 0; i < 4; i++)
            {
                writeStream.Write((byte)0xcc);
            }
        }
        private void Flush()
        {
            if (uncompressedStream == null)
            {
                return;
            }

            fileWriter.Write(MatfileHelper.MatlabDataTypeNumber(typeof(ZlibStream)));
            byte[] compressedBuffer = ZlibStream.CompressBuffer(uncompressedStream.ToArray());
            fileWriter.Write((UInt32)compressedBuffer.Length);
            fileWriter.Write(compressedBuffer);

            uncompressedStream = null;
        }
Example #5
0
        private void WriteFlags(Type arrayElementDataType)
        {
            //write 4 values for flag block

            //Array flags use uint32 data type
            writeStream.Write(MatfileHelper.MatlabDataTypeNumber(typeof(UInt32)));

            //flag block length (always 8)
            writeStream.Write((int)8);

            //array class
            writeStream.Write(MatfileHelper.MatlabArrayTypeNumber(arrayElementDataType));

            //padding (always 0)
            writeStream.Write((int)0);
        }
Example #6
0
        private void WriteDimensionsPlaceholder()
        {
            //data type contained in dimensions subelement: Int32
            writeStream.Write(MatfileHelper.MatlabDataTypeNumber(typeof(Int32)));

            //always 8 bytes long
            writeStream.Write((int)8);

            //store position, so we can later overwrite these 2 placeholders
            dimensionsStartPosition = writeStream.BaseStream.Position;

            //placeholder for first dimension
            for (int i = 0; i < dimensions.Length * MatfileHelper.MatlabBytesPerType(typeof(Int32)); i++)
            {
                writeStream.Write((byte)0xee);
            }

            totalPaddingAdded += writeStream.AdvanceTo8ByteBoundary();
        }
Example #7
0
        private void WriteName(string name)
        {
            //write 4 values for name block

            //data type contained in name block (always 1)
            writeStream.Write(MatfileHelper.MatlabDataTypeNumber(typeof(SByte)));

            //size (without padding!)
            int nameLength = name.Length;

            writeStream.Write((int)nameLength);

            //write name itself
            for (int i = 0; i < nameLength; i++)
            {
                writeStream.Write((byte)name[i]);
            }

            totalPaddingAdded += writeStream.AdvanceTo8ByteBoundary();
        }
        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(t.dataType, matrixStream.ReadBytes((int)t.length));
            }
            else
            {
                readBytes = (Array)t.data;
            }

            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(dataType, readBytes.Length);
                Array.Copy(readBytes, linearData, readBytes.Length);
                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(dataType));
            }

            if (reshapedData.Length == 1)
            {
                data = reshapedData.GetValue(0);
            }
            else
            {
                data = reshapedData;
            }
        }
Example #9
0
        private static void ReadMatrix(ref Variable vi, UInt32 length, BinaryReader matrixStream)
        {
            Tag  t;
            long offset = matrixStream.BaseStream.Position;

            //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

            //Dimensions - There are always 2 dimensions, so this
            //tag will never be of small data format, i.e. not checking for t.data
            t = MatfileHelper.ReadTag(matrixStream);
            int[] arrayDimensions = new int[t.length / MatfileHelper.MatlabBytesPerType(t.dataType)];
            int   elements        = 1;

            for (int i = 0; i < arrayDimensions.Length; i++)
            {
                int dimension = (int)matrixStream.ReadUInt32();
                arrayDimensions[arrayDimensions.Length - i - 1] = dimension;
                elements *= dimension;
            }
            //Don't keep single dimensions
            arrayDimensions = arrayDimensions.Where(x => x > 1).ToArray();
            //If by doing this, we end up without dimensions, it means we had a 1x...x1 array.
            //We need at least 1 dimension to instantiate the final array, so...
            if (arrayDimensions.Length == 0)
            {
                arrayDimensions = new int[1] {
                    1
                }
            }
            ;

            //Array name
            t = MatfileHelper.ReadTag(matrixStream);
            if (t.data != null)
            {
                sbyte[] varname = t.data as sbyte[];
                vi.name = Encoding.UTF8.GetString(Array.ConvertAll(varname, x => (byte)x));
            }
            else
            {
                byte[] varname = matrixStream.ReadBytes((int)t.length);
                vi.name = Encoding.UTF8.GetString(varname);
                MatfileHelper.AdvanceTo8ByteBoundary(matrixStream);
            }


            //Read and reshape data
            t = MatfileHelper.ReadTag(matrixStream);
            //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));
            }
            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 linearData = Array.CreateInstance(vi.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;
            }
            else //Readbytes is already in the correct type
            {
                Buffer.BlockCopy(readBytes, 0, reshapedData, 0, readBytes.Length * MatfileHelper.MatlabBytesPerType(vi.dataType));
            }

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

            //Move on in case the data didn't end on a 64 byte boundary
            matrixStream.BaseStream.Seek(offset + length, SeekOrigin.Begin);
        }
        private static void ReadMatrix(ref Variable vi, UInt32 length, BinaryReader matrixStream)
        {
            Tag  t;
            long offset = matrixStream.BaseStream.Position;

            //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) == 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
            t = MatfileHelper.ReadTag(matrixStream);
            int[] arrayDimensions = new int[t.length / MatfileHelper.MatlabBytesPerType(t.dataType)];
            int   elements        = 1;

            for (int i = 0; i < arrayDimensions.Length; i++)
            {
                int dimension = (int)matrixStream.ReadUInt32();// depends on sizeof(t.dataType) => MatfileHelper.MatlabBytesPerType(t.dataType)
                arrayDimensions[arrayDimensions.Length - i - 1] = dimension;
                elements *= dimension;
            }
            //Don't keep single dimensions
            arrayDimensions = arrayDimensions.Where(x => x > 1).ToArray();
            //If by doing this, we end up without dimensions, it means we had a 1x...x1 array.
            //We need at least 1 dimension to instantiate the final array, so...
            if (arrayDimensions.Length == 0)
            {
                arrayDimensions = new int[1] {
                    1
                }
            }
            ;

            //Array name
            t = MatfileHelper.ReadTag(matrixStream);
            if (t.data != null)
            {
                sbyte[] varname = t.data as sbyte[];
                vi.name = Encoding.UTF8.GetString(Array.ConvertAll(varname, x => (byte)x));
            }
            else
            {
                byte[] varname = matrixStream.ReadBytes((int)t.length);
                vi.name = Encoding.UTF8.GetString(varname);
                MatfileHelper.AdvanceTo8ByteBoundary(matrixStream);
            }


            //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);
        }