From 4c8141275535258539febd48192747681a22502f Mon Sep 17 00:00:00 2001 From: Mike Williams Date: Wed, 23 Mar 2016 10:29:12 -0400 Subject: [PATCH 1/2] Adding stream reading capabilities to MatFileReader --- CSMatIO.sln | 2 +- src/AssemblyInfo.cs | 6 +- src/CSMatIO.nuspec | 6 +- src/io/MatFileReader.cs | 1596 ++++++++++++++++++++------------------- 4 files changed, 807 insertions(+), 803 deletions(-) diff --git a/CSMatIO.sln b/CSMatIO.sln index 9cb1aa6..2c056a8 100644 --- a/CSMatIO.sln +++ b/CSMatIO.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csmatio", "src\csmatio.csproj", "{D6EB17BF-9074-484F-9950-E06169A3C39D}" EndProject diff --git a/src/AssemblyInfo.cs b/src/AssemblyInfo.cs index 6a98f88..d390e56 100644 --- a/src/AssemblyInfo.cs +++ b/src/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("csmatio")] -[assembly: AssemblyCopyright("Copyright © 2007, David A. Zier")] +[assembly: AssemblyCopyright("Copyright © 2016, Mike Williams, Copyright © 2007, David A. Zier")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -29,5 +29,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("1.0.0")] -[assembly: AssemblyFileVersion("1.0.0")] +[assembly: AssemblyVersion("1.0.1")] +[assembly: AssemblyFileVersion("1.0.1")] diff --git a/src/CSMatIO.nuspec b/src/CSMatIO.nuspec index da8304d..06034d5 100644 --- a/src/CSMatIO.nuspec +++ b/src/CSMatIO.nuspec @@ -2,8 +2,8 @@ CSMatIO - 1.0.0 - Sérgio aka AlienEnginner + 1.0.1 + Sérgio aka AlienEnginner, Mike Williams https://raw.githubusercontent.com/AlienEngineer/CSMatIO/master/LICENSE https://github.com/AlienEngineer/CSMatIO/wiki @@ -12,7 +12,7 @@ - Copyright (c) 2015 AlienEngineer + Copyright (c) 2016 Mike Williams, Copyright (c) 2015 AlienEngineer Matlab csmatio diff --git a/src/io/MatFileReader.cs b/src/io/MatFileReader.cs index 674e6d4..5a110a2 100644 --- a/src/io/MatFileReader.cs +++ b/src/io/MatFileReader.cs @@ -34,147 +34,151 @@ namespace csmatio.io /// // or get the collection of all arrays that were stored in the file /// Hashtable content = mfr.Content; /// - /// + /// + /// Mike Williams (mswillia) /// David Zier (david.zier@gmail.com) - public class MatFileReader - { - /// - /// MAT-file header - /// - private MatFileHeader _matFileHeader; - /// - /// Contianer for read MLArrays - /// - private Dictionary _data; - // /// - // /// Tells how bytes are organized in the buffer - // /// - // private ByteOrder _byteData; - /// - /// Array name filter - /// - private MatFileFilter _filter; - - - /// - /// Creates instance of MatFileReader and reads MAT-file with then name - /// fileName. - /// - /// - /// This method reads MAT-file without filtering. - /// - /// The name of the MAT-file to open - public MatFileReader(string fileName) : - this(fileName, new MatFileFilter()) - { - } - - - /// - /// Creates instance of MatFileReader and reads MAT-file with then name - /// fileName. - /// - /// - /// Results are filtered by MatFileFilter. Arrays that do not meet - /// filter match condition will not be available in results. - /// - /// The name of the MAT-file to open - /// MatFileFilter - public MatFileReader(string fileName, MatFileFilter filter) - { - _filter = filter; - _data = new Dictionary(); - - // Try to open up the file as read-only - FileStream dataIn; - try - { - dataIn = new FileStream(fileName, FileMode.Open, FileAccess.Read); - } - catch (FileNotFoundException) - { - throw new MatlabIOException("Could not open the file '" + fileName + "' for reading!"); - } - - // try and read in the file until completed - try - { - ReadHeader(dataIn); - - for (; ; ) - { - ReadData(dataIn); - } - } - catch (EndOfStreamException) - { - // Catch to break out of the for loop - } - catch (IOException e) - { - throw new MatlabIOException("Error in reading MAT-file '" + fileName + "':\n" + e.ToString()); - } - finally - { - dataIn.Close(); - } - } - - /// - /// Gets MAT-file header. - /// - public MatFileHeader MatFileHeader - { - get { return _matFileHeader; } - } - - /// - /// Returns list of MLArray objects that were inside the MAT-file - /// - public List Data - { - get { return new List(_data.Values); } - } - - /// - /// Returns the value to which the read file maps the specific array name. - /// - /// - /// Returns null if the file contains no content for this name. - /// - /// Array name - /// The MLArray to which this file maps the specific name, - /// or null if the file contains no content for this name - public MLArray GetMLArray(string name) - { - return _data.ContainsKey(name) ? (MLArray)_data[name] : null; - } - - /// - /// Returns a map of MLArray objects that were inside MAT-file. - /// - /// MLArrays are keyed with the MLArrays' name. - public Dictionary Content - { - get { return _data; } - } - - /// - /// Decompresses (inflates) bytes from input stream. - /// - /// - /// Stream marker is being set at +numOfBytes position of the stream. - /// - /// Input byte buffer stream. - /// The number of bytes to be read. - /// new ByteBuffer with the inflated block of data. - /// When an error occurs while reading or inflating the buffer. - private Stream Inflate(Stream buf, int numOfBytes) - { - if (buf.Length - buf.Position < numOfBytes) - { - throw new MatlabIOException("Compressed buffer length miscalculated!"); - } + public class MatFileReader + { + /// + /// MAT-file header + /// + private MatFileHeader _matFileHeader; + /// + /// Contianer for read MLArrays + /// + private Dictionary _data; + // /// + // /// Tells how bytes are organized in the buffer + // /// + // private ByteOrder _byteData; + /// + /// Array name filter + /// + private MatFileFilter _filter; + + /// + /// Creates instance of MatFileReader and reads MAT-file with then name + /// fileName. + /// + /// + /// This method reads MAT-file without filtering. + /// + /// The name of the MAT-file to open + public MatFileReader(string fileName) : + this(fileName, new MatFileFilter()) + { + } + + + /// + /// Creates instance of MatFileReader and reads MAT-file with then name + /// fileName. + /// + /// + /// Results are filtered by MatFileFilter. Arrays that do not meet + /// filter match condition will not be available in results. + /// + /// The name of the MAT-file to open + /// MatFileFilter + public MatFileReader(string fileName, MatFileFilter filter) + : this(new FileStream(fileName, FileMode.Open, FileAccess.Read), filter) + { + } + + /// + /// Creates instance of MatFileReader and reads MAT-file from the + /// FileStream. + /// + /// + /// Results are filtered by MatFileFilter. Arrays that do not meet + /// filter match condition will not be available in results. + /// + /// The stream the MAT-stream will read + /// MatFileFilter + public MatFileReader(Stream dataIn, MatFileFilter filter) + { + _filter = filter; + _data = new Dictionary(); + + // try and read in the stream until completed + try + { + ReadHeader(dataIn); + + for (; ; ) + { + ReadData(dataIn); + } + } + catch (EndOfStreamException) + { + // Catch to break out of the for loop + } + catch (IOException e) + { + throw new MatlabIOException("Error in reading MAT-stream:\n" + e.ToString()); + } + finally + { + dataIn.Close(); + } + } + + /// + /// Gets MAT-file header. + /// + public MatFileHeader MatFileHeader + { + get { return _matFileHeader; } + } + + /// + /// Returns list of MLArray objects that were inside the MAT-file + /// + public List Data + { + get { return new List(_data.Values); } + } + + /// + /// Returns the value to which the read file maps the specific array name. + /// + /// + /// Returns null if the file contains no content for this name. + /// + /// Array name + /// The MLArray to which this file maps the specific name, + /// or null if the file contains no content for this name + public MLArray GetMLArray(string name) + { + return _data.ContainsKey(name) ? (MLArray)_data[name] : null; + } + + /// + /// Returns a map of MLArray objects that were inside MAT-file. + /// + /// MLArrays are keyed with the MLArrays' name. + public Dictionary Content + { + get { return _data; } + } + + /// + /// Decompresses (inflates) bytes from input stream. + /// + /// + /// Stream marker is being set at +numOfBytes position of the stream. + /// + /// Input byte buffer stream. + /// The number of bytes to be read. + /// new ByteBuffer with the inflated block of data. + /// When an error occurs while reading or inflating the buffer. + private Stream Inflate(Stream buf, int numOfBytes) + { + if (buf.Length - buf.Position < numOfBytes) + { + throw new MatlabIOException("Compressed buffer length miscalculated!"); + } #if false // test code! @@ -185,8 +189,8 @@ private Stream Inflate(Stream buf, int numOfBytes) File.WriteAllBytes("DeflatedMatlabData.bin", byteBuffer); #endif - try - { + try + { #if NET20 MemoryStream inflatedStream = new MemoryStream(numOfBytes); @@ -209,671 +213,671 @@ private Stream Inflate(Stream buf, int numOfBytes) #endif #if NET40 || NET45 // skip CRC (at end) and zip format (0x789C at begin) - buf.Position += 2; - numOfBytes -= 6; + buf.Position += 2; + numOfBytes -= 6; + + MemoryStream compressedStream = new MemoryStream(); + int data; + do + { + data = buf.ReadByte(); + if (data != -1) + { + compressedStream.WriteByte((byte)(data & 0x000000FF)); + } + } + while (data != -1 && compressedStream.Length < numOfBytes); + + // skip CRC + buf.Position += 4; + compressedStream.Position = 0; + MemoryStream decompressedStream = new MemoryStream(); + using (DeflateStream df = new DeflateStream(compressedStream, CompressionMode.Decompress)) + { + do + { + data = df.ReadByte(); + if (data != -1) + { + decompressedStream.WriteByte((byte)(data & 0x000000FF)); + } + } + while (data != -1); + } + decompressedStream.Position = 0; + return decompressedStream; +#endif + } + catch (IOException e) + { + throw new MatlabIOException("Could not decompress data: " + e); + } + } + + /// + /// Reads data from the BinaryReader stream. Searches for either + /// miCOMPRESSED data or miMATRIX data. + /// + /// + /// Compressed data is inflated and the product is recursively passed back + /// to this same method. + /// + /// The input BinaryReader stream. + private void ReadData(Stream buf) + { + // read data + ISMatTag tag = new ISMatTag(buf); + switch (tag.Type) + { + case MatDataTypes.miCOMPRESSED: + // inflate and recur + { + Stream uncompressed = Inflate(buf, tag.Size); + ReadData(uncompressed); + uncompressed.Close(); + } + break; + case MatDataTypes.miMATRIX: + // read in the matrix + int pos = (int)buf.Position; + int red, toread; + + MLArray element = ReadMatrix(buf, true); + + if (element != null) + { + _data.Add(element.Name, element); + } + else + { + red = (int)buf.Position - pos; + toread = tag.Size - red; + buf.Position = buf.Position + toread; + } + red = (int)buf.Position - pos; + + toread = tag.Size - red; + + if (toread != 0) + { + throw new MatlabIOException("Matrix was not read fully! " + toread + " remaining in the buffer."); + } + break; + default: + throw new MatlabIOException("Incorrect data tag: " + tag); + + } + } + + /// + /// Reads miMATRIX from the input stream. + /// + /// + /// If reading was not finished (which is normal for filtered results) + /// returns null. + /// + /// The BinaryReader input stream. + /// When true informs that if this is a top level + /// matrix. + /// MLArray or null if matrix does not match filter + private MLArray ReadMatrix(Stream buf, bool isRoot) + { + // result + MLArray mlArray = null; + ISMatTag tag; + + // read flags + int[] flags = ReadFlags(buf); + int attributes = (flags.Length != 0) ? flags[0] : 0; + int nzmax = (flags.Length != 0) ? flags[1] : 0; + int type = attributes & 0xff; + + // read Array dimension + int[] dims = ReadDimension(buf); + + // read Array name + string name = ReadName(buf); + + // If this array is filtered out return immediately + if (isRoot && !_filter.Matches(name)) + { + return null; + } + + // read data + switch (type) + { + case MLArray.mxSTRUCT_CLASS: + MLStructure mlStruct = new MLStructure(name, dims, type, attributes); + + BinaryReader br = new BinaryReader(buf); + + // field name length - this subelement always uses the compressed data element format + tag = new ISMatTag(br.BaseStream); + int maxlen = br.ReadInt32(); + + // Read fields data as Int8 + tag = new ISMatTag(br.BaseStream); + // calculate number of fields + int numOfFields = tag.Size / maxlen; + + // padding after field names + int padding = (tag.Size % 8) != 0 ? 8 - tag.Size % 8 : 0; + + string[] fieldNames = new string[numOfFields]; + for (int i = 0; i < numOfFields; i++) + { + byte[] names = new byte[maxlen]; + br.Read(names, 0, names.Length); + fieldNames[i] = ZeroEndByteArrayToString(names); + } + br.ReadBytes(padding); + + // read fields + for (int index = 0; index < mlStruct.M * mlStruct.N; index++) + { + for (int i = 0; i < numOfFields; i++) + { + // read matrix recursively + tag = new ISMatTag(br.BaseStream); + if (tag.Size > 0) + { + MLArray fieldValue = ReadMatrix(br.BaseStream, false); + mlStruct[fieldNames[i], index] = fieldValue; + } + else + { + mlStruct[fieldNames[i], index] = new MLEmptyArray(); + } + } + } + mlArray = mlStruct; + //br.Close(); + break; + case MLArray.mxCELL_CLASS: + MLCell cell = new MLCell(name, dims, type, attributes); + for (int i = 0; i < cell.M * cell.N; i++) + { + tag = new ISMatTag(buf); + if (tag.Size > 0) + { + MLArray cellmatrix = ReadMatrix(buf, false); + cell[i] = cellmatrix; + } + else + { + cell[i] = new MLEmptyArray(); + } + } + mlArray = cell; + break; + case MLArray.mxDOUBLE_CLASS: + mlArray = new MLDouble(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); - MemoryStream compressedStream = new MemoryStream(); - int data; - do - { - data = buf.ReadByte(); - if (data != -1) - { - compressedStream.WriteByte((byte)(data & 0x000000FF)); - } - } - while (data != -1 && compressedStream.Length < numOfBytes); + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxSINGLE_CLASS: + mlArray = new MLSingle(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); - // skip CRC - buf.Position += 4; - compressedStream.Position = 0; - MemoryStream decompressedStream = new MemoryStream(); - using (DeflateStream df = new DeflateStream(compressedStream, CompressionMode.Decompress)) - { - do - { - data = df.ReadByte(); - if (data != -1) - { - decompressedStream.WriteByte((byte)(data & 0x000000FF)); - } - } - while (data != -1); - } - decompressedStream.Position = 0; - return decompressedStream; -#endif - } - catch (IOException e) - { - throw new MatlabIOException("Could not decompress data: " + e); - } - } - - /// - /// Reads data from the BinaryReader stream. Searches for either - /// miCOMPRESSED data or miMATRIX data. - /// - /// - /// Compressed data is inflated and the product is recursively passed back - /// to this same method. - /// - /// The input BinaryReader stream. - private void ReadData(Stream buf) - { - // read data - ISMatTag tag = new ISMatTag(buf); - switch (tag.Type) - { - case MatDataTypes.miCOMPRESSED: - // inflate and recur - { - Stream uncompressed = Inflate(buf, tag.Size); - ReadData(uncompressed); - uncompressed.Close(); - } - break; - case MatDataTypes.miMATRIX: - // read in the matrix - int pos = (int)buf.Position; - int red, toread; - - MLArray element = ReadMatrix(buf, true); - - if (element != null) - { - _data.Add(element.Name, element); - } - else - { - red = (int)buf.Position - pos; - toread = tag.Size - red; - buf.Position = buf.Position + toread; - } - red = (int)buf.Position - pos; - - toread = tag.Size - red; - - if (toread != 0) - { - throw new MatlabIOException("Matrix was not read fully! " + toread + " remaining in the buffer."); - } - break; - default: - throw new MatlabIOException("Incorrect data tag: " + tag); - - } - } - - /// - /// Reads miMATRIX from the input stream. - /// - /// - /// If reading was not finished (which is normal for filtered results) - /// returns null. - /// - /// The BinaryReader input stream. - /// When true informs that if this is a top level - /// matrix. - /// MLArray or null if matrix does not match filter - private MLArray ReadMatrix(Stream buf, bool isRoot) - { - // result - MLArray mlArray = null; - ISMatTag tag; - - // read flags - int[] flags = ReadFlags(buf); - int attributes = (flags.Length != 0) ? flags[0] : 0; - int nzmax = (flags.Length != 0) ? flags[1] : 0; - int type = attributes & 0xff; - - // read Array dimension - int[] dims = ReadDimension(buf); - - // read Array name - string name = ReadName(buf); - - // If this array is filtered out return immediately - if (isRoot && !_filter.Matches(name)) - { - return null; - } - - // read data - switch (type) - { - case MLArray.mxSTRUCT_CLASS: - MLStructure mlStruct = new MLStructure(name, dims, type, attributes); - - BinaryReader br = new BinaryReader(buf); - - // field name length - this subelement always uses the compressed data element format - tag = new ISMatTag(br.BaseStream); - int maxlen = br.ReadInt32(); - - // Read fields data as Int8 - tag = new ISMatTag(br.BaseStream); - // calculate number of fields - int numOfFields = tag.Size / maxlen; - - // padding after field names - int padding = (tag.Size % 8) != 0 ? 8 - tag.Size % 8 : 0; - - string[] fieldNames = new string[numOfFields]; - for (int i = 0; i < numOfFields; i++) - { - byte[] names = new byte[maxlen]; - br.Read(names, 0, names.Length); - fieldNames[i] = ZeroEndByteArrayToString(names); - } - br.ReadBytes(padding); - - // read fields - for (int index = 0; index < mlStruct.M * mlStruct.N; index++) - { - for (int i = 0; i < numOfFields; i++) - { - // read matrix recursively - tag = new ISMatTag(br.BaseStream); - if (tag.Size > 0) - { - MLArray fieldValue = ReadMatrix(br.BaseStream, false); - mlStruct[fieldNames[i], index] = fieldValue; - } - else - { - mlStruct[fieldNames[i], index] = new MLEmptyArray(); - } - } - } - mlArray = mlStruct; - //br.Close(); - break; - case MLArray.mxCELL_CLASS: - MLCell cell = new MLCell(name, dims, type, attributes); - for (int i = 0; i < cell.M * cell.N; i++) - { - tag = new ISMatTag(buf); - if (tag.Size > 0) - { - MLArray cellmatrix = ReadMatrix(buf, false); - cell[i] = cellmatrix; - } - else - { - cell[i] = new MLEmptyArray(); - } - } - mlArray = cell; - break; - case MLArray.mxDOUBLE_CLASS: - mlArray = new MLDouble(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT8_CLASS: + mlArray = new MLUInt8(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, (IByteStorageSupport)mlArray); - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxSINGLE_CLASS: - mlArray = new MLSingle(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT8_CLASS: - mlArray = new MLUInt8(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT8_CLASS: - mlArray = new MLInt8(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT16_CLASS: - mlArray = new MLUInt16(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT16_CLASS: - mlArray = new MLInt16(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT32_CLASS: - mlArray = new MLUInt32(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT32_CLASS: - mlArray = new MLInt32(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT64_CLASS: - mlArray = new MLUInt64(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + } + break; + case MLArray.mxINT8_CLASS: + mlArray = new MLInt8(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, (IByteStorageSupport)mlArray); - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT64_CLASS: - mlArray = new MLInt64(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + } + break; + case MLArray.mxUINT16_CLASS: + mlArray = new MLUInt16(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, (IByteStorageSupport)mlArray); - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxCHAR_CLASS: - MLChar mlchar = new MLChar(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - char[] ac = tag.ReadToCharArray(); - for (int i = 0; i < ac.Length; i++) - { - mlchar.SetChar(ac[i], i); - } - mlArray = mlchar; - break; - case MLArray.mxSPARSE_CLASS: - MLSparse sparse = new MLSparse(name, dims, attributes, nzmax); - - // read ir (row indices) - tag = new ISMatTag(buf); - int[] ir = tag.ReadToIntArray(); - // read jc (column indices) - tag = new ISMatTag(buf); - int[] jc = tag.ReadToIntArray(); - - // read pr (real part) - tag = new ISMatTag(buf); - double[] ad1 = tag.ReadToDoubleArray(); - int n = 0; - for (int i = 0; i < ir.Length; i++) - { - if (i < sparse.N) - { - n = jc[i]; - } - sparse.SetReal(ad1[i], ir[i], n); - } - - //read pi (imaginary part) - if (sparse.IsComplex) - { - tag = new ISMatTag(buf); - double[] ad2 = tag.ReadToDoubleArray(); - - int n1 = 0; - for (int i = 0; i < ir.Length; i++) - { - if (i < sparse.N) - { - n1 = jc[i]; - } - sparse.SetImaginary(ad2[i], ir[i], n1); - } - } - mlArray = sparse; - break; - default: - throw new MatlabIOException("Incorrect Matlab array class: " + MLArray.TypeToString(type)); - } - return mlArray; - } - - /// - /// Converts a byte array to string. It assumes that the string ends with \0 value. - /// - /// Byte array containing the string. - /// String retrieved from byte array - private string ZeroEndByteArrayToString(byte[] bytes) - { - StringBuilder sb = new StringBuilder(); - foreach (byte b in bytes) - { - if (b == 0) - break; - sb.Append((char)b); - } - return sb.ToString(); - } - - /// - /// Reads Matrix flags. - /// - /// BinaryReader input stream - /// Flags int array - private int[] ReadFlags(Stream buf) - { - ISMatTag tag = new ISMatTag(buf); - - int[] flags = tag.ReadToIntArray(); - - return flags; - } - - /// - /// Reads Matrix dimensions. - /// - /// BinaryReader input stream - /// Dimensions int array - private int[] ReadDimension(Stream buf) - { - ISMatTag tag = new ISMatTag(buf); - int[] dims = tag.ReadToIntArray(); - return dims; - } - - /// - /// Reads Matrix name. - /// - /// BinaryReader input stream - /// string - private string ReadName(Stream buf) - { - string s; - - ISMatTag tag = new ISMatTag(buf); - char[] ac = tag.ReadToCharArray(); - s = new string(ac); - - return s; - } - - /// - /// Reads MAT-file header. - /// - /// BinaryReader input stream - private void ReadHeader(Stream buf) - { - string description; - int version; - BinaryReader br = new BinaryReader(buf); - byte[] endianIndicator = new byte[2]; - - //descriptive text 116 bytes - byte[] descriptionBuffer = new byte[116]; - br.Read(descriptionBuffer, 0, descriptionBuffer.Length); - - description = ZeroEndByteArrayToString(descriptionBuffer); - - if (!description.StartsWith("MATLAB 5.0 MAT-file")) - { - throw new MatlabIOException("This is not a valid MATLAB 5.0 MAT-file."); - } - - // subsyst data offset 8 bytes - br.ReadBytes(8); - - byte[] bversion = new byte[2]; - //version 2 bytes - br.Read(bversion, 0, bversion.Length); - - //endian indicator 2 bytes - br.Read(endianIndicator, 0, endianIndicator.Length); - - // Program reading the MAT-file must perform byte swapping to interpret the data - // in the MAT-file correctly - if ((char)endianIndicator[0] == 'I' && (char)endianIndicator[1] == 'M') - { - // We have a Little Endian MAT-file - version = bversion[1] & 0xff | bversion[0] << 8; - } - else - { - // right now, this version of CSMatIO does not support Big Endian - throw new MatlabIOException("This version of CSMatIO does not support Big Endian."); - } - - _matFileHeader = new MatFileHeader(description, version, endianIndicator); - } - - /// - /// TAG operator. Facilitates reading operations. - /// - /// - /// Note: Reading from buffer and/or stream modifies it's position. - /// - /// David Zier (david.zier@gmail.com) - private class ISMatTag : MatTag - { - /// - /// A ByteBuffer object for this tag - /// - public BinaryReader Buf; - private int padding; - - /// - /// Create an ISMatTag from a ByteBuffer. - /// - /// ByteBuffer - public ISMatTag(Stream buf) : - base(0, 0) - { - Buf = new BinaryReader(buf); - int tmp = Buf.ReadInt32(); - - bool compressed; - // data not packed in the tag - if (tmp >> 16 == 0) - { - _type = tmp; - _size = Buf.ReadInt32(); - compressed = false; - } - else // data _packed_ in the tag (compressed) - { - _size = tmp >> 16; // 2 more significant bytes - _type = tmp & 0xffff; // 2 less significant bytes - compressed = true; - } + } + break; + case MLArray.mxINT16_CLASS: + mlArray = new MLInt16(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT32_CLASS: + mlArray = new MLUInt32(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxINT32_CLASS: + mlArray = new MLInt32(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT64_CLASS: + mlArray = new MLUInt64(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxINT64_CLASS: + mlArray = new MLInt64(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); - padding = GetPadding(_size, compressed); - } - - ///// - ///// Gets the size of the ISMatTag - ///// - //public int Size - //{ - // get { return (int)Buf.BaseStream.Length; } - //} - - /// - /// Read MAT-file tag to a byte buffer. - /// - /// ByteBuffer - /// ByteStorageSupport - public void ReadToByteBuffer( ByteBuffer buff, IByteStorageSupport storage ) - { - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - int elements = _size / SizeOf(); - mfis.ReadToByteBuffer(buff, elements, storage); - //skip padding - if (padding > 0) - Buf.ReadBytes(padding); - } - - /// - /// Read MAT-file tag to a byte array - /// - /// byte[] - public byte[] ReadToByteArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - byte[] ab = new byte[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ab[i] = mfis.ReadByte(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ab; - } - - /// - /// Read MAT-file tag to a double array - /// - /// double[] - public double[] ReadToDoubleArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - double[] ad = new double[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ad[i] = mfis.ReadDouble(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ad; - } - - /// - /// Read MAT-file tag to a int array - /// - /// int[] - public int[] ReadToIntArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - int[] ai = new int[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ai[i] = mfis.ReadInt(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ai; - } - - /// - /// Read MAT-file tag to a char array - /// - /// int[] - public char[] ReadToCharArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - char[] ac = new char[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ac[i] = mfis.ReadChar(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ac; - } - } - } + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxCHAR_CLASS: + MLChar mlchar = new MLChar(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + char[] ac = tag.ReadToCharArray(); + for (int i = 0; i < ac.Length; i++) + { + mlchar.SetChar(ac[i], i); + } + mlArray = mlchar; + break; + case MLArray.mxSPARSE_CLASS: + MLSparse sparse = new MLSparse(name, dims, attributes, nzmax); + + // read ir (row indices) + tag = new ISMatTag(buf); + int[] ir = tag.ReadToIntArray(); + // read jc (column indices) + tag = new ISMatTag(buf); + int[] jc = tag.ReadToIntArray(); + + // read pr (real part) + tag = new ISMatTag(buf); + double[] ad1 = tag.ReadToDoubleArray(); + int n = 0; + for (int i = 0; i < ir.Length; i++) + { + if (i < sparse.N) + { + n = jc[i]; + } + sparse.SetReal(ad1[i], ir[i], n); + } + + //read pi (imaginary part) + if (sparse.IsComplex) + { + tag = new ISMatTag(buf); + double[] ad2 = tag.ReadToDoubleArray(); + + int n1 = 0; + for (int i = 0; i < ir.Length; i++) + { + if (i < sparse.N) + { + n1 = jc[i]; + } + sparse.SetImaginary(ad2[i], ir[i], n1); + } + } + mlArray = sparse; + break; + default: + throw new MatlabIOException("Incorrect Matlab array class: " + MLArray.TypeToString(type)); + } + return mlArray; + } + + /// + /// Converts a byte array to string. It assumes that the string ends with \0 value. + /// + /// Byte array containing the string. + /// String retrieved from byte array + private string ZeroEndByteArrayToString(byte[] bytes) + { + StringBuilder sb = new StringBuilder(); + foreach (byte b in bytes) + { + if (b == 0) + break; + sb.Append((char)b); + } + return sb.ToString(); + } + + /// + /// Reads Matrix flags. + /// + /// BinaryReader input stream + /// Flags int array + private int[] ReadFlags(Stream buf) + { + ISMatTag tag = new ISMatTag(buf); + + int[] flags = tag.ReadToIntArray(); + + return flags; + } + + /// + /// Reads Matrix dimensions. + /// + /// BinaryReader input stream + /// Dimensions int array + private int[] ReadDimension(Stream buf) + { + ISMatTag tag = new ISMatTag(buf); + int[] dims = tag.ReadToIntArray(); + return dims; + } + + /// + /// Reads Matrix name. + /// + /// BinaryReader input stream + /// string + private string ReadName(Stream buf) + { + string s; + + ISMatTag tag = new ISMatTag(buf); + char[] ac = tag.ReadToCharArray(); + s = new string(ac); + + return s; + } + + /// + /// Reads MAT-file header. + /// + /// BinaryReader input stream + private void ReadHeader(Stream buf) + { + string description; + int version; + BinaryReader br = new BinaryReader(buf); + byte[] endianIndicator = new byte[2]; + + //descriptive text 116 bytes + byte[] descriptionBuffer = new byte[116]; + br.Read(descriptionBuffer, 0, descriptionBuffer.Length); + + description = ZeroEndByteArrayToString(descriptionBuffer); + + if (!description.StartsWith("MATLAB 5.0 MAT-file")) + { + throw new MatlabIOException("This is not a valid MATLAB 5.0 MAT-file."); + } + + // subsyst data offset 8 bytes + br.ReadBytes(8); + + byte[] bversion = new byte[2]; + //version 2 bytes + br.Read(bversion, 0, bversion.Length); + + //endian indicator 2 bytes + br.Read(endianIndicator, 0, endianIndicator.Length); + + // Program reading the MAT-file must perform byte swapping to interpret the data + // in the MAT-file correctly + if ((char)endianIndicator[0] == 'I' && (char)endianIndicator[1] == 'M') + { + // We have a Little Endian MAT-file + version = bversion[1] & 0xff | bversion[0] << 8; + } + else + { + // right now, this version of CSMatIO does not support Big Endian + throw new MatlabIOException("This version of CSMatIO does not support Big Endian."); + } + + _matFileHeader = new MatFileHeader(description, version, endianIndicator); + } + + /// + /// TAG operator. Facilitates reading operations. + /// + /// + /// Note: Reading from buffer and/or stream modifies it's position. + /// + /// David Zier (david.zier@gmail.com) + private class ISMatTag : MatTag + { + /// + /// A ByteBuffer object for this tag + /// + public BinaryReader Buf; + private int padding; + + /// + /// Create an ISMatTag from a ByteBuffer. + /// + /// ByteBuffer + public ISMatTag(Stream buf) : + base(0, 0) + { + Buf = new BinaryReader(buf); + int tmp = Buf.ReadInt32(); + + bool compressed; + // data not packed in the tag + if (tmp >> 16 == 0) + { + _type = tmp; + _size = Buf.ReadInt32(); + compressed = false; + } + else // data _packed_ in the tag (compressed) + { + _size = tmp >> 16; // 2 more significant bytes + _type = tmp & 0xffff; // 2 less significant bytes + compressed = true; + } + + + padding = GetPadding(_size, compressed); + } + + ///// + ///// Gets the size of the ISMatTag + ///// + //public int Size + //{ + // get { return (int)Buf.BaseStream.Length; } + //} + + /// + /// Read MAT-file tag to a byte buffer. + /// + /// ByteBuffer + /// ByteStorageSupport + public void ReadToByteBuffer(ByteBuffer buff, IByteStorageSupport storage) + { + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + int elements = _size / SizeOf(); + mfis.ReadToByteBuffer(buff, elements, storage); + //skip padding + if (padding > 0) + Buf.ReadBytes(padding); + } + + /// + /// Read MAT-file tag to a byte array + /// + /// byte[] + public byte[] ReadToByteArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + byte[] ab = new byte[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ab[i] = mfis.ReadByte(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ab; + } + + /// + /// Read MAT-file tag to a double array + /// + /// double[] + public double[] ReadToDoubleArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + double[] ad = new double[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ad[i] = mfis.ReadDouble(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ad; + } + + /// + /// Read MAT-file tag to a int array + /// + /// int[] + public int[] ReadToIntArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + int[] ai = new int[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ai[i] = mfis.ReadInt(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ai; + } + + /// + /// Read MAT-file tag to a char array + /// + /// int[] + public char[] ReadToCharArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + char[] ac = new char[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ac[i] = mfis.ReadChar(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ac; + } + } + } } From efb4a1f1670d3ad123202f0434c986daed745366 Mon Sep 17 00:00:00 2001 From: Mike Williams Date: Wed, 23 Mar 2016 10:34:44 -0400 Subject: [PATCH 2/2] Fixing indents --- src/io/MatFileReader.cs | 1626 +++++++++++++++++++-------------------- 1 file changed, 813 insertions(+), 813 deletions(-) diff --git a/src/io/MatFileReader.cs b/src/io/MatFileReader.cs index 5a110a2..3e1f1e1 100644 --- a/src/io/MatFileReader.cs +++ b/src/io/MatFileReader.cs @@ -34,151 +34,151 @@ namespace csmatio.io /// // or get the collection of all arrays that were stored in the file /// Hashtable content = mfr.Content; /// - /// - /// Mike Williams (mswillia) + /// + /// Mike Williams (mswillia) /// David Zier (david.zier@gmail.com) - public class MatFileReader - { - /// - /// MAT-file header - /// - private MatFileHeader _matFileHeader; - /// - /// Contianer for read MLArrays - /// - private Dictionary _data; - // /// - // /// Tells how bytes are organized in the buffer - // /// - // private ByteOrder _byteData; - /// - /// Array name filter - /// - private MatFileFilter _filter; - - /// - /// Creates instance of MatFileReader and reads MAT-file with then name - /// fileName. - /// - /// - /// This method reads MAT-file without filtering. - /// - /// The name of the MAT-file to open - public MatFileReader(string fileName) : - this(fileName, new MatFileFilter()) - { - } - - - /// - /// Creates instance of MatFileReader and reads MAT-file with then name - /// fileName. - /// - /// - /// Results are filtered by MatFileFilter. Arrays that do not meet - /// filter match condition will not be available in results. - /// - /// The name of the MAT-file to open - /// MatFileFilter - public MatFileReader(string fileName, MatFileFilter filter) - : this(new FileStream(fileName, FileMode.Open, FileAccess.Read), filter) - { - } - - /// - /// Creates instance of MatFileReader and reads MAT-file from the - /// FileStream. - /// - /// - /// Results are filtered by MatFileFilter. Arrays that do not meet - /// filter match condition will not be available in results. - /// - /// The stream the MAT-stream will read - /// MatFileFilter - public MatFileReader(Stream dataIn, MatFileFilter filter) - { - _filter = filter; - _data = new Dictionary(); - - // try and read in the stream until completed - try - { - ReadHeader(dataIn); - - for (; ; ) - { - ReadData(dataIn); - } - } - catch (EndOfStreamException) - { - // Catch to break out of the for loop - } - catch (IOException e) - { - throw new MatlabIOException("Error in reading MAT-stream:\n" + e.ToString()); - } - finally - { - dataIn.Close(); - } - } - - /// - /// Gets MAT-file header. - /// - public MatFileHeader MatFileHeader - { - get { return _matFileHeader; } - } - - /// - /// Returns list of MLArray objects that were inside the MAT-file - /// - public List Data - { - get { return new List(_data.Values); } - } - - /// - /// Returns the value to which the read file maps the specific array name. - /// - /// - /// Returns null if the file contains no content for this name. - /// - /// Array name - /// The MLArray to which this file maps the specific name, - /// or null if the file contains no content for this name - public MLArray GetMLArray(string name) - { - return _data.ContainsKey(name) ? (MLArray)_data[name] : null; - } - - /// - /// Returns a map of MLArray objects that were inside MAT-file. - /// - /// MLArrays are keyed with the MLArrays' name. - public Dictionary Content - { - get { return _data; } - } - - /// - /// Decompresses (inflates) bytes from input stream. - /// - /// - /// Stream marker is being set at +numOfBytes position of the stream. - /// - /// Input byte buffer stream. - /// The number of bytes to be read. - /// new ByteBuffer with the inflated block of data. - /// When an error occurs while reading or inflating the buffer. - private Stream Inflate(Stream buf, int numOfBytes) - { - if (buf.Length - buf.Position < numOfBytes) - { - throw new MatlabIOException("Compressed buffer length miscalculated!"); - } + public class MatFileReader + { + /// + /// MAT-file header + /// + private MatFileHeader _matFileHeader; + /// + /// Contianer for read MLArrays + /// + private Dictionary _data; + // /// + // /// Tells how bytes are organized in the buffer + // /// + // private ByteOrder _byteData; + /// + /// Array name filter + /// + private MatFileFilter _filter; + + /// + /// Creates instance of MatFileReader and reads MAT-file with then name + /// fileName. + /// + /// + /// This method reads MAT-file without filtering. + /// + /// The name of the MAT-file to open + public MatFileReader(string fileName) : + this(fileName, new MatFileFilter()) + { + } + + + /// + /// Creates instance of MatFileReader and reads MAT-file with then name + /// fileName. + /// + /// + /// Results are filtered by MatFileFilter. Arrays that do not meet + /// filter match condition will not be available in results. + /// + /// The name of the MAT-file to open + /// MatFileFilter + public MatFileReader(string fileName, MatFileFilter filter) + : this(new FileStream(fileName, FileMode.Open, FileAccess.Read), filter) + { + } + + /// + /// Creates instance of MatFileReader and reads MAT-file from the + /// FileStream. + /// + /// + /// Results are filtered by MatFileFilter. Arrays that do not meet + /// filter match condition will not be available in results. + /// + /// The stream the MAT-stream will read + /// MatFileFilter + public MatFileReader(Stream dataIn, MatFileFilter filter) + { + _filter = filter; + _data = new Dictionary(); + + // try and read in the stream until completed + try + { + ReadHeader(dataIn); + + for (; ; ) + { + ReadData(dataIn); + } + } + catch (EndOfStreamException) + { + // Catch to break out of the for loop + } + catch (IOException e) + { + throw new MatlabIOException("Error in reading MAT-stream:\n" + e.ToString()); + } + finally + { + dataIn.Close(); + } + } + + /// + /// Gets MAT-file header. + /// + public MatFileHeader MatFileHeader + { + get { return _matFileHeader; } + } + + /// + /// Returns list of MLArray objects that were inside the MAT-file + /// + public List Data + { + get { return new List(_data.Values); } + } + + /// + /// Returns the value to which the read file maps the specific array name. + /// + /// + /// Returns null if the file contains no content for this name. + /// + /// Array name + /// The MLArray to which this file maps the specific name, + /// or null if the file contains no content for this name + public MLArray GetMLArray(string name) + { + return _data.ContainsKey(name) ? (MLArray)_data[name] : null; + } + + /// + /// Returns a map of MLArray objects that were inside MAT-file. + /// + /// MLArrays are keyed with the MLArrays' name. + public Dictionary Content + { + get { return _data; } + } + + /// + /// Decompresses (inflates) bytes from input stream. + /// + /// + /// Stream marker is being set at +numOfBytes position of the stream. + /// + /// Input byte buffer stream. + /// The number of bytes to be read. + /// new ByteBuffer with the inflated block of data. + /// When an error occurs while reading or inflating the buffer. + private Stream Inflate(Stream buf, int numOfBytes) + { + if (buf.Length - buf.Position < numOfBytes) + { + throw new MatlabIOException("Compressed buffer length miscalculated!"); + } #if false // test code! @@ -189,8 +189,8 @@ private Stream Inflate(Stream buf, int numOfBytes) File.WriteAllBytes("DeflatedMatlabData.bin", byteBuffer); #endif - try - { + try + { #if NET20 MemoryStream inflatedStream = new MemoryStream(numOfBytes); @@ -212,672 +212,672 @@ private Stream Inflate(Stream buf, int numOfBytes) return inflatedStream; #endif #if NET40 || NET45 - // skip CRC (at end) and zip format (0x789C at begin) - buf.Position += 2; - numOfBytes -= 6; - - MemoryStream compressedStream = new MemoryStream(); - int data; - do - { - data = buf.ReadByte(); - if (data != -1) - { - compressedStream.WriteByte((byte)(data & 0x000000FF)); - } - } - while (data != -1 && compressedStream.Length < numOfBytes); - - // skip CRC - buf.Position += 4; - compressedStream.Position = 0; - MemoryStream decompressedStream = new MemoryStream(); - using (DeflateStream df = new DeflateStream(compressedStream, CompressionMode.Decompress)) - { - do - { - data = df.ReadByte(); - if (data != -1) - { - decompressedStream.WriteByte((byte)(data & 0x000000FF)); - } - } - while (data != -1); - } - decompressedStream.Position = 0; - return decompressedStream; + // skip CRC (at end) and zip format (0x789C at begin) + buf.Position += 2; + numOfBytes -= 6; + + MemoryStream compressedStream = new MemoryStream(); + int data; + do + { + data = buf.ReadByte(); + if (data != -1) + { + compressedStream.WriteByte((byte)(data & 0x000000FF)); + } + } + while (data != -1 && compressedStream.Length < numOfBytes); + + // skip CRC + buf.Position += 4; + compressedStream.Position = 0; + MemoryStream decompressedStream = new MemoryStream(); + using (DeflateStream df = new DeflateStream(compressedStream, CompressionMode.Decompress)) + { + do + { + data = df.ReadByte(); + if (data != -1) + { + decompressedStream.WriteByte((byte)(data & 0x000000FF)); + } + } + while (data != -1); + } + decompressedStream.Position = 0; + return decompressedStream; #endif - } - catch (IOException e) - { - throw new MatlabIOException("Could not decompress data: " + e); - } - } - - /// - /// Reads data from the BinaryReader stream. Searches for either - /// miCOMPRESSED data or miMATRIX data. - /// - /// - /// Compressed data is inflated and the product is recursively passed back - /// to this same method. - /// - /// The input BinaryReader stream. - private void ReadData(Stream buf) - { - // read data - ISMatTag tag = new ISMatTag(buf); - switch (tag.Type) - { - case MatDataTypes.miCOMPRESSED: - // inflate and recur - { - Stream uncompressed = Inflate(buf, tag.Size); - ReadData(uncompressed); - uncompressed.Close(); - } - break; - case MatDataTypes.miMATRIX: - // read in the matrix - int pos = (int)buf.Position; - int red, toread; - - MLArray element = ReadMatrix(buf, true); - - if (element != null) - { - _data.Add(element.Name, element); - } - else - { - red = (int)buf.Position - pos; - toread = tag.Size - red; - buf.Position = buf.Position + toread; - } - red = (int)buf.Position - pos; - - toread = tag.Size - red; - - if (toread != 0) - { - throw new MatlabIOException("Matrix was not read fully! " + toread + " remaining in the buffer."); - } - break; - default: - throw new MatlabIOException("Incorrect data tag: " + tag); - - } - } - - /// - /// Reads miMATRIX from the input stream. - /// - /// - /// If reading was not finished (which is normal for filtered results) - /// returns null. - /// - /// The BinaryReader input stream. - /// When true informs that if this is a top level - /// matrix. - /// MLArray or null if matrix does not match filter - private MLArray ReadMatrix(Stream buf, bool isRoot) - { - // result - MLArray mlArray = null; - ISMatTag tag; - - // read flags - int[] flags = ReadFlags(buf); - int attributes = (flags.Length != 0) ? flags[0] : 0; - int nzmax = (flags.Length != 0) ? flags[1] : 0; - int type = attributes & 0xff; - - // read Array dimension - int[] dims = ReadDimension(buf); - - // read Array name - string name = ReadName(buf); - - // If this array is filtered out return immediately - if (isRoot && !_filter.Matches(name)) - { - return null; - } - - // read data - switch (type) - { - case MLArray.mxSTRUCT_CLASS: - MLStructure mlStruct = new MLStructure(name, dims, type, attributes); - - BinaryReader br = new BinaryReader(buf); - - // field name length - this subelement always uses the compressed data element format - tag = new ISMatTag(br.BaseStream); - int maxlen = br.ReadInt32(); - - // Read fields data as Int8 - tag = new ISMatTag(br.BaseStream); - // calculate number of fields - int numOfFields = tag.Size / maxlen; - - // padding after field names - int padding = (tag.Size % 8) != 0 ? 8 - tag.Size % 8 : 0; - - string[] fieldNames = new string[numOfFields]; - for (int i = 0; i < numOfFields; i++) - { - byte[] names = new byte[maxlen]; - br.Read(names, 0, names.Length); - fieldNames[i] = ZeroEndByteArrayToString(names); - } - br.ReadBytes(padding); - - // read fields - for (int index = 0; index < mlStruct.M * mlStruct.N; index++) - { - for (int i = 0; i < numOfFields; i++) - { - // read matrix recursively - tag = new ISMatTag(br.BaseStream); - if (tag.Size > 0) - { - MLArray fieldValue = ReadMatrix(br.BaseStream, false); - mlStruct[fieldNames[i], index] = fieldValue; - } - else - { - mlStruct[fieldNames[i], index] = new MLEmptyArray(); - } - } - } - mlArray = mlStruct; - //br.Close(); - break; - case MLArray.mxCELL_CLASS: - MLCell cell = new MLCell(name, dims, type, attributes); - for (int i = 0; i < cell.M * cell.N; i++) - { - tag = new ISMatTag(buf); - if (tag.Size > 0) - { - MLArray cellmatrix = ReadMatrix(buf, false); - cell[i] = cellmatrix; - } - else - { - cell[i] = new MLEmptyArray(); - } - } - mlArray = cell; - break; - case MLArray.mxDOUBLE_CLASS: - mlArray = new MLDouble(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxSINGLE_CLASS: - mlArray = new MLSingle(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT8_CLASS: - mlArray = new MLUInt8(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT8_CLASS: - mlArray = new MLInt8(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT16_CLASS: - mlArray = new MLUInt16(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT16_CLASS: - mlArray = new MLInt16(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT32_CLASS: - mlArray = new MLUInt32(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT32_CLASS: - mlArray = new MLInt32(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxUINT64_CLASS: - mlArray = new MLUInt64(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxINT64_CLASS: - mlArray = new MLInt64(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, - (IByteStorageSupport)mlArray); - - // read complex - if (mlArray.IsComplex) - { - tag = new ISMatTag(buf); - tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, - (IByteStorageSupport)mlArray); - } - break; - case MLArray.mxCHAR_CLASS: - MLChar mlchar = new MLChar(name, dims, type, attributes); - //read real - tag = new ISMatTag(buf); - char[] ac = tag.ReadToCharArray(); - for (int i = 0; i < ac.Length; i++) - { - mlchar.SetChar(ac[i], i); - } - mlArray = mlchar; - break; - case MLArray.mxSPARSE_CLASS: - MLSparse sparse = new MLSparse(name, dims, attributes, nzmax); - - // read ir (row indices) - tag = new ISMatTag(buf); - int[] ir = tag.ReadToIntArray(); - // read jc (column indices) - tag = new ISMatTag(buf); - int[] jc = tag.ReadToIntArray(); - - // read pr (real part) - tag = new ISMatTag(buf); - double[] ad1 = tag.ReadToDoubleArray(); - int n = 0; - for (int i = 0; i < ir.Length; i++) - { - if (i < sparse.N) - { - n = jc[i]; - } - sparse.SetReal(ad1[i], ir[i], n); - } - - //read pi (imaginary part) - if (sparse.IsComplex) - { - tag = new ISMatTag(buf); - double[] ad2 = tag.ReadToDoubleArray(); - - int n1 = 0; - for (int i = 0; i < ir.Length; i++) - { - if (i < sparse.N) - { - n1 = jc[i]; - } - sparse.SetImaginary(ad2[i], ir[i], n1); - } - } - mlArray = sparse; - break; - default: - throw new MatlabIOException("Incorrect Matlab array class: " + MLArray.TypeToString(type)); - } - return mlArray; - } - - /// - /// Converts a byte array to string. It assumes that the string ends with \0 value. - /// - /// Byte array containing the string. - /// String retrieved from byte array - private string ZeroEndByteArrayToString(byte[] bytes) - { - StringBuilder sb = new StringBuilder(); - foreach (byte b in bytes) - { - if (b == 0) - break; - sb.Append((char)b); - } - return sb.ToString(); - } - - /// - /// Reads Matrix flags. - /// - /// BinaryReader input stream - /// Flags int array - private int[] ReadFlags(Stream buf) - { - ISMatTag tag = new ISMatTag(buf); - - int[] flags = tag.ReadToIntArray(); - - return flags; - } - - /// - /// Reads Matrix dimensions. - /// - /// BinaryReader input stream - /// Dimensions int array - private int[] ReadDimension(Stream buf) - { - ISMatTag tag = new ISMatTag(buf); - int[] dims = tag.ReadToIntArray(); - return dims; - } - - /// - /// Reads Matrix name. - /// - /// BinaryReader input stream - /// string - private string ReadName(Stream buf) - { - string s; - - ISMatTag tag = new ISMatTag(buf); - char[] ac = tag.ReadToCharArray(); - s = new string(ac); - - return s; - } - - /// - /// Reads MAT-file header. - /// - /// BinaryReader input stream - private void ReadHeader(Stream buf) - { - string description; - int version; - BinaryReader br = new BinaryReader(buf); - byte[] endianIndicator = new byte[2]; - - //descriptive text 116 bytes - byte[] descriptionBuffer = new byte[116]; - br.Read(descriptionBuffer, 0, descriptionBuffer.Length); - - description = ZeroEndByteArrayToString(descriptionBuffer); - - if (!description.StartsWith("MATLAB 5.0 MAT-file")) - { - throw new MatlabIOException("This is not a valid MATLAB 5.0 MAT-file."); - } - - // subsyst data offset 8 bytes - br.ReadBytes(8); - - byte[] bversion = new byte[2]; - //version 2 bytes - br.Read(bversion, 0, bversion.Length); - - //endian indicator 2 bytes - br.Read(endianIndicator, 0, endianIndicator.Length); - - // Program reading the MAT-file must perform byte swapping to interpret the data - // in the MAT-file correctly - if ((char)endianIndicator[0] == 'I' && (char)endianIndicator[1] == 'M') - { - // We have a Little Endian MAT-file - version = bversion[1] & 0xff | bversion[0] << 8; - } - else - { - // right now, this version of CSMatIO does not support Big Endian - throw new MatlabIOException("This version of CSMatIO does not support Big Endian."); - } - - _matFileHeader = new MatFileHeader(description, version, endianIndicator); - } - - /// - /// TAG operator. Facilitates reading operations. - /// - /// - /// Note: Reading from buffer and/or stream modifies it's position. - /// - /// David Zier (david.zier@gmail.com) - private class ISMatTag : MatTag - { - /// - /// A ByteBuffer object for this tag - /// - public BinaryReader Buf; - private int padding; - - /// - /// Create an ISMatTag from a ByteBuffer. - /// - /// ByteBuffer - public ISMatTag(Stream buf) : - base(0, 0) - { - Buf = new BinaryReader(buf); - int tmp = Buf.ReadInt32(); - - bool compressed; - // data not packed in the tag - if (tmp >> 16 == 0) - { - _type = tmp; - _size = Buf.ReadInt32(); - compressed = false; - } - else // data _packed_ in the tag (compressed) - { - _size = tmp >> 16; // 2 more significant bytes - _type = tmp & 0xffff; // 2 less significant bytes - compressed = true; - } - - - padding = GetPadding(_size, compressed); - } - - ///// - ///// Gets the size of the ISMatTag - ///// - //public int Size - //{ - // get { return (int)Buf.BaseStream.Length; } - //} - - /// - /// Read MAT-file tag to a byte buffer. - /// - /// ByteBuffer - /// ByteStorageSupport - public void ReadToByteBuffer(ByteBuffer buff, IByteStorageSupport storage) - { - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - int elements = _size / SizeOf(); - mfis.ReadToByteBuffer(buff, elements, storage); - //skip padding - if (padding > 0) - Buf.ReadBytes(padding); - } - - /// - /// Read MAT-file tag to a byte array - /// - /// byte[] - public byte[] ReadToByteArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - byte[] ab = new byte[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ab[i] = mfis.ReadByte(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ab; - } - - /// - /// Read MAT-file tag to a double array - /// - /// double[] - public double[] ReadToDoubleArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - double[] ad = new double[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ad[i] = mfis.ReadDouble(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ad; - } - - /// - /// Read MAT-file tag to a int array - /// - /// int[] - public int[] ReadToIntArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - int[] ai = new int[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ai[i] = mfis.ReadInt(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ai; - } - - /// - /// Read MAT-file tag to a char array - /// - /// int[] - public char[] ReadToCharArray() - { - // allocate memory for array elements - int elements = _size / SizeOf(); - char[] ac = new char[elements]; - - MatFileInputStream mfis = new MatFileInputStream(Buf, _type); - - for (int i = 0; i < elements; i++) - ac[i] = mfis.ReadChar(); - - // skip padding - if (padding > 0) - Buf.ReadBytes(padding); - return ac; - } - } - } + } + catch (IOException e) + { + throw new MatlabIOException("Could not decompress data: " + e); + } + } + + /// + /// Reads data from the BinaryReader stream. Searches for either + /// miCOMPRESSED data or miMATRIX data. + /// + /// + /// Compressed data is inflated and the product is recursively passed back + /// to this same method. + /// + /// The input BinaryReader stream. + private void ReadData(Stream buf) + { + // read data + ISMatTag tag = new ISMatTag(buf); + switch (tag.Type) + { + case MatDataTypes.miCOMPRESSED: + // inflate and recur + { + Stream uncompressed = Inflate(buf, tag.Size); + ReadData(uncompressed); + uncompressed.Close(); + } + break; + case MatDataTypes.miMATRIX: + // read in the matrix + int pos = (int)buf.Position; + int red, toread; + + MLArray element = ReadMatrix(buf, true); + + if (element != null) + { + _data.Add(element.Name, element); + } + else + { + red = (int)buf.Position - pos; + toread = tag.Size - red; + buf.Position = buf.Position + toread; + } + red = (int)buf.Position - pos; + + toread = tag.Size - red; + + if (toread != 0) + { + throw new MatlabIOException("Matrix was not read fully! " + toread + " remaining in the buffer."); + } + break; + default: + throw new MatlabIOException("Incorrect data tag: " + tag); + + } + } + + /// + /// Reads miMATRIX from the input stream. + /// + /// + /// If reading was not finished (which is normal for filtered results) + /// returns null. + /// + /// The BinaryReader input stream. + /// When true informs that if this is a top level + /// matrix. + /// MLArray or null if matrix does not match filter + private MLArray ReadMatrix(Stream buf, bool isRoot) + { + // result + MLArray mlArray = null; + ISMatTag tag; + + // read flags + int[] flags = ReadFlags(buf); + int attributes = (flags.Length != 0) ? flags[0] : 0; + int nzmax = (flags.Length != 0) ? flags[1] : 0; + int type = attributes & 0xff; + + // read Array dimension + int[] dims = ReadDimension(buf); + + // read Array name + string name = ReadName(buf); + + // If this array is filtered out return immediately + if (isRoot && !_filter.Matches(name)) + { + return null; + } + + // read data + switch (type) + { + case MLArray.mxSTRUCT_CLASS: + MLStructure mlStruct = new MLStructure(name, dims, type, attributes); + + BinaryReader br = new BinaryReader(buf); + + // field name length - this subelement always uses the compressed data element format + tag = new ISMatTag(br.BaseStream); + int maxlen = br.ReadInt32(); + + // Read fields data as Int8 + tag = new ISMatTag(br.BaseStream); + // calculate number of fields + int numOfFields = tag.Size / maxlen; + + // padding after field names + int padding = (tag.Size % 8) != 0 ? 8 - tag.Size % 8 : 0; + + string[] fieldNames = new string[numOfFields]; + for (int i = 0; i < numOfFields; i++) + { + byte[] names = new byte[maxlen]; + br.Read(names, 0, names.Length); + fieldNames[i] = ZeroEndByteArrayToString(names); + } + br.ReadBytes(padding); + + // read fields + for (int index = 0; index < mlStruct.M * mlStruct.N; index++) + { + for (int i = 0; i < numOfFields; i++) + { + // read matrix recursively + tag = new ISMatTag(br.BaseStream); + if (tag.Size > 0) + { + MLArray fieldValue = ReadMatrix(br.BaseStream, false); + mlStruct[fieldNames[i], index] = fieldValue; + } + else + { + mlStruct[fieldNames[i], index] = new MLEmptyArray(); + } + } + } + mlArray = mlStruct; + //br.Close(); + break; + case MLArray.mxCELL_CLASS: + MLCell cell = new MLCell(name, dims, type, attributes); + for (int i = 0; i < cell.M * cell.N; i++) + { + tag = new ISMatTag(buf); + if (tag.Size > 0) + { + MLArray cellmatrix = ReadMatrix(buf, false); + cell[i] = cellmatrix; + } + else + { + cell[i] = new MLEmptyArray(); + } + } + mlArray = cell; + break; + case MLArray.mxDOUBLE_CLASS: + mlArray = new MLDouble(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxSINGLE_CLASS: + mlArray = new MLSingle(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT8_CLASS: + mlArray = new MLUInt8(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxINT8_CLASS: + mlArray = new MLInt8(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT16_CLASS: + mlArray = new MLUInt16(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxINT16_CLASS: + mlArray = new MLInt16(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT32_CLASS: + mlArray = new MLUInt32(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxINT32_CLASS: + mlArray = new MLInt32(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxUINT64_CLASS: + mlArray = new MLUInt64(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxINT64_CLASS: + mlArray = new MLInt64(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).RealByteBuffer, + (IByteStorageSupport)mlArray); + + // read complex + if (mlArray.IsComplex) + { + tag = new ISMatTag(buf); + tag.ReadToByteBuffer(((MLNumericArray)mlArray).ImaginaryByteBuffer, + (IByteStorageSupport)mlArray); + } + break; + case MLArray.mxCHAR_CLASS: + MLChar mlchar = new MLChar(name, dims, type, attributes); + //read real + tag = new ISMatTag(buf); + char[] ac = tag.ReadToCharArray(); + for (int i = 0; i < ac.Length; i++) + { + mlchar.SetChar(ac[i], i); + } + mlArray = mlchar; + break; + case MLArray.mxSPARSE_CLASS: + MLSparse sparse = new MLSparse(name, dims, attributes, nzmax); + + // read ir (row indices) + tag = new ISMatTag(buf); + int[] ir = tag.ReadToIntArray(); + // read jc (column indices) + tag = new ISMatTag(buf); + int[] jc = tag.ReadToIntArray(); + + // read pr (real part) + tag = new ISMatTag(buf); + double[] ad1 = tag.ReadToDoubleArray(); + int n = 0; + for (int i = 0; i < ir.Length; i++) + { + if (i < sparse.N) + { + n = jc[i]; + } + sparse.SetReal(ad1[i], ir[i], n); + } + + //read pi (imaginary part) + if (sparse.IsComplex) + { + tag = new ISMatTag(buf); + double[] ad2 = tag.ReadToDoubleArray(); + + int n1 = 0; + for (int i = 0; i < ir.Length; i++) + { + if (i < sparse.N) + { + n1 = jc[i]; + } + sparse.SetImaginary(ad2[i], ir[i], n1); + } + } + mlArray = sparse; + break; + default: + throw new MatlabIOException("Incorrect Matlab array class: " + MLArray.TypeToString(type)); + } + return mlArray; + } + + /// + /// Converts a byte array to string. It assumes that the string ends with \0 value. + /// + /// Byte array containing the string. + /// String retrieved from byte array + private string ZeroEndByteArrayToString(byte[] bytes) + { + StringBuilder sb = new StringBuilder(); + foreach (byte b in bytes) + { + if (b == 0) + break; + sb.Append((char)b); + } + return sb.ToString(); + } + + /// + /// Reads Matrix flags. + /// + /// BinaryReader input stream + /// Flags int array + private int[] ReadFlags(Stream buf) + { + ISMatTag tag = new ISMatTag(buf); + + int[] flags = tag.ReadToIntArray(); + + return flags; + } + + /// + /// Reads Matrix dimensions. + /// + /// BinaryReader input stream + /// Dimensions int array + private int[] ReadDimension(Stream buf) + { + ISMatTag tag = new ISMatTag(buf); + int[] dims = tag.ReadToIntArray(); + return dims; + } + + /// + /// Reads Matrix name. + /// + /// BinaryReader input stream + /// string + private string ReadName(Stream buf) + { + string s; + + ISMatTag tag = new ISMatTag(buf); + char[] ac = tag.ReadToCharArray(); + s = new string(ac); + + return s; + } + + /// + /// Reads MAT-file header. + /// + /// BinaryReader input stream + private void ReadHeader(Stream buf) + { + string description; + int version; + BinaryReader br = new BinaryReader(buf); + byte[] endianIndicator = new byte[2]; + + //descriptive text 116 bytes + byte[] descriptionBuffer = new byte[116]; + br.Read(descriptionBuffer, 0, descriptionBuffer.Length); + + description = ZeroEndByteArrayToString(descriptionBuffer); + + if (!description.StartsWith("MATLAB 5.0 MAT-file")) + { + throw new MatlabIOException("This is not a valid MATLAB 5.0 MAT-file."); + } + + // subsyst data offset 8 bytes + br.ReadBytes(8); + + byte[] bversion = new byte[2]; + //version 2 bytes + br.Read(bversion, 0, bversion.Length); + + //endian indicator 2 bytes + br.Read(endianIndicator, 0, endianIndicator.Length); + + // Program reading the MAT-file must perform byte swapping to interpret the data + // in the MAT-file correctly + if ((char)endianIndicator[0] == 'I' && (char)endianIndicator[1] == 'M') + { + // We have a Little Endian MAT-file + version = bversion[1] & 0xff | bversion[0] << 8; + } + else + { + // right now, this version of CSMatIO does not support Big Endian + throw new MatlabIOException("This version of CSMatIO does not support Big Endian."); + } + + _matFileHeader = new MatFileHeader(description, version, endianIndicator); + } + + /// + /// TAG operator. Facilitates reading operations. + /// + /// + /// Note: Reading from buffer and/or stream modifies it's position. + /// + /// David Zier (david.zier@gmail.com) + private class ISMatTag : MatTag + { + /// + /// A ByteBuffer object for this tag + /// + public BinaryReader Buf; + private int padding; + + /// + /// Create an ISMatTag from a ByteBuffer. + /// + /// ByteBuffer + public ISMatTag(Stream buf) : + base(0, 0) + { + Buf = new BinaryReader(buf); + int tmp = Buf.ReadInt32(); + + bool compressed; + // data not packed in the tag + if (tmp >> 16 == 0) + { + _type = tmp; + _size = Buf.ReadInt32(); + compressed = false; + } + else // data _packed_ in the tag (compressed) + { + _size = tmp >> 16; // 2 more significant bytes + _type = tmp & 0xffff; // 2 less significant bytes + compressed = true; + } + + + padding = GetPadding(_size, compressed); + } + + ///// + ///// Gets the size of the ISMatTag + ///// + //public int Size + //{ + // get { return (int)Buf.BaseStream.Length; } + //} + + /// + /// Read MAT-file tag to a byte buffer. + /// + /// ByteBuffer + /// ByteStorageSupport + public void ReadToByteBuffer(ByteBuffer buff, IByteStorageSupport storage) + { + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + int elements = _size / SizeOf(); + mfis.ReadToByteBuffer(buff, elements, storage); + //skip padding + if (padding > 0) + Buf.ReadBytes(padding); + } + + /// + /// Read MAT-file tag to a byte array + /// + /// byte[] + public byte[] ReadToByteArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + byte[] ab = new byte[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ab[i] = mfis.ReadByte(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ab; + } + + /// + /// Read MAT-file tag to a double array + /// + /// double[] + public double[] ReadToDoubleArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + double[] ad = new double[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ad[i] = mfis.ReadDouble(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ad; + } + + /// + /// Read MAT-file tag to a int array + /// + /// int[] + public int[] ReadToIntArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + int[] ai = new int[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ai[i] = mfis.ReadInt(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ai; + } + + /// + /// Read MAT-file tag to a char array + /// + /// int[] + public char[] ReadToCharArray() + { + // allocate memory for array elements + int elements = _size / SizeOf(); + char[] ac = new char[elements]; + + MatFileInputStream mfis = new MatFileInputStream(Buf, _type); + + for (int i = 0; i < elements; i++) + ac[i] = mfis.ReadChar(); + + // skip padding + if (padding > 0) + Buf.ReadBytes(padding); + return ac; + } + } + } }