/// <summary> /// Read the next data element from the stream /// </summary> /// <param name="name">On exit, the variable name</param> /// <returns>The data value, as a .NET object</returns> protected object Matlab5DataElement(out string name) { MatType dataType = (MatType)ReadInt(); int numBytes = ReadInt(); byte[] bytes = new byte[numBytes]; if (reader.Read(bytes, 0, numBytes) < numBytes) { throw new EndOfStreamException(); } if (dataType == MatType.COMPRESSED) { // MAT file compression uses Zlib format, which is the same as Deflate but with an extra header and footer. // To use DeflateStream, we must first remove this header. bytes = RemoveRfc1950Header(bytes); var stream = new DeflateStream(new MemoryStream(bytes), CompressionMode.Decompress); MatlabReader unzipReader = new MatlabReader(stream); return(unzipReader.Matlab5DataElement(out name)); } else { MatlabReader eltReader = new MatlabReader(new MemoryStream(bytes)); var result = eltReader.Parse(dataType, out name); return(result); } }
/// <summary> /// Read all variables from a file and store them in a dictionary /// </summary> /// <param name="fileName">The name of a MAT file</param> /// <returns>A dictionary that maps variable names into values</returns> public static Dictionary <string, object> Read(string fileName) { using (MatlabReader r = new MatlabReader(fileName)) { return(r.ReadAll()); } }
/// <summary> /// Write a named struct whose fields are the columns of a csv file /// </summary> /// <param name="name"></param> /// <param name="path"></param> public void WriteFromCsv(string name, string path) { Dictionary <string, List <string> > dict = MatlabReader.ReadCsv(path); // try to convert strings into numbers Dictionary <string, object> dict2 = new Dictionary <string, object>(); foreach (var entry in dict) { bool isDouble = true; List <double> doubles = new List <double>(); foreach (string s in entry.Value) { double d; if (s.Length == 0) { d = double.NaN; doubles.Add(d); } else if (double.TryParse(s, out d)) { doubles.Add(d); } else { isDouble = false; break; } } if (isDouble) { dict2.Add(entry.Key, doubles); } else { dict2.Add(entry.Key, entry.Value); } } Write(name, dict2); }
/// <summary> /// Write a named array to the stream /// </summary> /// <param name="name"></param> /// <param name="array"></param> public void WriteArray(string name, Array array) { Type eltType = array.GetType().GetElementType(); mxClass dataClass = GetDataClass(eltType); // convert to a valid variable name name = MakeValidVariableName(name); // pad the name to an 8-byte boundary int numNameBytes = ((name.Length + 7) / 8) * 8; // precompute the cell bytes int numDataBytes = 0; int numDims = array.Rank; int numElts = array.Length; int[] sizes = new int[numDims]; for (int i = 0; i < numDims; i++) { sizes[i] = array.GetLength(i); } MatlabReader.Reverse(sizes); int[] strides = StringUtil.ArrayStrides(sizes); MatlabReader.Reverse(sizes); int[] index = new int[numDims]; List <byte[]> bytes = new List <byte[]>(); Stream oldWriter = writer; try { for (int i = 0; i < numElts; i++) { StringUtil.LinearIndexToMultidimensionalIndex(i, strides, index); MatlabReader.Reverse(index); object cell = array.GetValue(index); MemoryStream ms = new MemoryStream(128); writer = ms; if (dataClass == mxClass.CELL) { Write("", cell); } else if (dataClass == mxClass.DOUBLE) { Write((double)cell); } else if (dataClass == mxClass.SINGLE) { Write((Single)cell); } else if (dataClass == mxClass.INT8) { Write((byte)cell); } else if (dataClass == mxClass.INT16) { Write((short)cell); } else if (dataClass == mxClass.UINT16) { Write((ushort)cell); } else if (dataClass == mxClass.INT32) { Write((int)cell); } else if (dataClass == mxClass.UINT32) { Write((uint)cell); } else if (dataClass == mxClass.INT64) { Write((long)cell); } else if (dataClass == mxClass.UINT64) { Write((ulong)cell); } else { throw new NotImplementedException(dataClass.ToString()); } byte[] valueBytes = ms.ToArray(); bytes.Add(valueBytes); numDataBytes += valueBytes.Length; } } finally { writer = oldWriter; } // compute total size of buffer int sizeBytes = numDims * 4; if (numDims % 2 == 1) { sizeBytes += 4; } int numBytes = 32 + sizeBytes + numNameBytes + numDataBytes; if (dataClass != mxClass.CELL) { numBytes += 8; } // write the data type field Write(MatType.MATRIX); Write(numBytes); // number of bytes // write the array flags Write(MatType.UINT32); Write(8); // 8 bytes to follow Write((int)dataClass); Write(0); // reserved // write the dimension field Write(MatType.INT32); if (numDims == 1) { Write(8); // 8 bytes to follow Write(sizes[0]); Write(1); } else { Write(numDims * 4); for (int i = 0; i < numDims; i++) { Write(sizes[i]); } if (numDims % 2 == 1) { Write(0); } } // write the name Write(MatType.INT8); Write(name.Length); // length of name in bytes Write(name, numNameBytes); if (dataClass != mxClass.CELL) { MatType elementClass = GetElementClass(eltType); Write((int)elementClass); Write(numDataBytes); } // write the cell values for (int i = 0; i < bytes.Count; i++) { Write(bytes[i]); } }