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