/// <summary> /// Adds a matrix from the actual file into our presentation of a matlab file. /// </summary> /// <param name="data">The data of the matrix.</param> /// <param name="file">The <see cref="MatlabFile"/> instance.</param> private void AddMatrix(byte[] data, MatlabFile file) { using (var ms = new MemoryStream(data)) { using (var reader = new BinaryReader(ms)) { // skip tag - doesn't tell us anything we don't already know reader.BaseStream.Seek(8, SeekOrigin.Current); var arrayClass = (ArrayClass)reader.ReadByte(); var flags = reader.ReadByte(); var isComplex = (flags & (byte)ArrayFlags.Complex) == (byte)ArrayFlags.Complex; if (isComplex) { throw new NotSupportedException(Resources.ComplexMatricesNotSupported); } // skip unneeded bytes reader.BaseStream.Seek(10, SeekOrigin.Current); var numDimensions = reader.ReadInt32() / 8; if (numDimensions > 2) { throw new NotSupportedException(Resources.MoreThan2D); } var rows = reader.ReadInt32(); var columns = reader.ReadInt32(); // skip unneeded bytes reader.BaseStream.Seek(2, SeekOrigin.Current); int size = reader.ReadInt16(); var smallBlock = true; if (size == 0) { size = reader.ReadInt32(); smallBlock = false; } var name = Encoding.ASCII.GetString(reader.ReadBytes(size)); AlignData(reader.BaseStream, size, smallBlock); // only grab wanted objects if (_names.Count != 0 && !_names.Contains(name)) { return; } var type = (DataType)reader.ReadInt16(); size = reader.ReadInt16(); if (size == 0) { size = reader.ReadInt32(); } Matrix<float> matrix; switch (arrayClass) { case ArrayClass.Sparse: matrix = PopulateSparseMatrix(reader, rows, columns, size); break; case ArrayClass.Function: case ArrayClass.Character: case ArrayClass.Object: case ArrayClass.Structure: case ArrayClass.Cell: case ArrayClass.Unknown: throw new NotImplementedException(); default: matrix = PopulateDenseMatrix(type, reader, rows, columns); break; } file.Matrices.Add(name, matrix); if (file.FirstMatrixName == null) { file.FirstMatrixName = name; } } } }
/// <summary> /// Parses the file. /// </summary> /// <returns>The parsed Matlab file as a <see cref="MatlabFile"/> object.</returns> public MatlabFile Parse() { var file = new MatlabFile(); using (var reader = new BinaryReader(_stream)) { file.HeaderText = Encoding.ASCII.GetString(reader.ReadBytes(116)); // skipping subsystem offsets reader.BaseStream.Position = 126; if (reader.ReadByte() != LittleEndianIndicator) { throw new NotSupportedException(Resources.BigEndianNotSupported); } // skip version since it is always 0x0100. reader.BaseStream.Position = 128; var length = _stream.Length; // for each data block add a matlab object to the file. while (reader.BaseStream.Position < length) { var type = (DataType)reader.ReadInt16(); int size = reader.ReadInt16(); var smallBlock = true; if (size == 0) { size = reader.ReadInt32(); smallBlock = false; } byte[] data; if (type == DataType.Compressed) { data = DecompressBlock(reader.ReadBytes(size), ref type); } else { data = new byte[size]; reader.Read(data, 0, size); AlignData(reader.BaseStream, size, smallBlock); } if (type == DataType.Matrix) { AddMatrix(data, file); } else { throw new NotSupportedException(string.Format(Resources.NotSupportedType, type)); } } } return file; }