/// <summary> /// Open the file ready for reading. /// </summary> /// <exception cref="System.Exception"> /// Cannot find headings and units line in + _FileName /// or /// Cannot find last row of file: + _FileName /// </exception> private void Open() { _Constants.Clear(); ReadApsimHeader(inStreamReader); if (Headings != null) { FirstLinePosition = inStreamReader.Position; // Read in first line. StringCollection Words = new StringCollection(); GetNextLine(inStreamReader, ref Words); ColumnTypes = DetermineColumnTypes(inStreamReader, Words); // Get first date. object[] values = ConvertWordsToObjects(Words, ColumnTypes); try { _FirstDate = GetDateFromValues(values); } catch (Exception err) { throw new Exception("Unable to parse first date in file " + _FileName + ": " + err.Message); } // Now we need to seek to the end of file and find the last full line in the file. inStreamReader.Seek(0, SeekOrigin.End); if (inStreamReader.Position >= 1000 && inStreamReader.Position - 1000 > FirstLinePosition) { inStreamReader.Seek(-1000, SeekOrigin.End); inStreamReader.ReadLine(); // throw away partial line. } else { inStreamReader.Seek(FirstLinePosition, SeekOrigin.Begin); } while (GetNextLine(inStreamReader, ref Words)) { } // Get the date from the last line. if (Words.Count == 0) { throw new Exception("Cannot find last row of file: " + _FileName); } values = ConvertWordsToObjects(Words, ColumnTypes); _LastDate = GetDateFromValues(values); inStreamReader.Seek(FirstLinePosition, SeekOrigin.Begin); } }
/// <summary> /// Reads the apsim header lines. /// </summary> /// <param name="inData">The in.</param> /// <param name="constantLines">The constant lines.</param> /// <param name="headingLines">The heading lines.</param> private void ReadApsimHeaderLines(StreamReaderRandomAccess inData, ref StringCollection constantLines, ref StringCollection headingLines) { string PreviousLine = ""; while (!inData.EndOfStream) { string Line = inData.ReadLine(); int PosEquals = Line.IndexOf('='); if (PosEquals != -1) { // constant found. constantLines.Add(Line); } else { if (IsCSVFile) { headingLines.Add(Line); break; } char[] whitespace = { ' ', '\t' }; int PosFirstNonBlankChar = StringUtilities.IndexNotOfAny(Line, whitespace); if (PosFirstNonBlankChar != -1 && Line[PosFirstNonBlankChar] == '(') { headingLines.Add(PreviousLine); headingLines.Add(Line); break; } } PreviousLine = Line; } }
/// <summary> /// Return the next line in the file as a collection of words. /// </summary> /// <param name="inData">The in.</param> /// <param name="words">The words.</param> /// <returns></returns> /// <exception cref="System.Exception">Invalid number of values on line: + Line + \r\nin file: + _FileName</exception> private bool GetNextLine(StreamReaderRandomAccess inData, ref StringCollection words) { if (inData.EndOfStream) { return(false); } string Line = inData.ReadLine(); if (Line == null || Line.Length == 0) { return(false); } if (Line.IndexOf("!") > 0) //used to ignore "!" in a row { Line = Line.Substring(0, Line.IndexOf("!") - 1); } if (IsCSVFile) { words.Clear(); Line = Line.TrimEnd(','); words.AddRange(Line.Split(",".ToCharArray())); } else { words = StringUtilities.SplitStringHonouringQuotes(Line, " \t"); } if (words.Count != Headings.Count) { throw new Exception("Invalid number of values on line: " + Line + "\r\nin file: " + _FileName); } // Remove leading / trailing double quote chars. for (int i = 0; i < words.Count; i++) { words[i] = words[i].Trim("\"".ToCharArray()); } return(true); }
/// <summary> /// Return the next line in the file as a collection of words. /// </summary> /// <param name="inData">The in.</param> /// <param name="words">The words.</param> /// <returns></returns> /// <exception cref="System.Exception">Invalid number of values on line: + Line + \r\nin file: + _FileName</exception> private bool GetNextLine(StreamReaderRandomAccess inData, ref StringCollection words) { if (inData.EndOfStream) return false; string Line = inData.ReadLine(); if (Line == null || Line.Length == 0) return false; if (Line.IndexOf("!") > 0) //used to ignore "!" in a row Line = Line.Substring(0, Line.IndexOf("!") - 1); if (IsCSVFile) { words.Clear(); Line = Line.TrimEnd(','); words.AddRange(Line.Split(",".ToCharArray())); } else words = StringUtilities.SplitStringHonouringQuotes(Line, " \t"); if (words.Count != Headings.Count) throw new Exception("Invalid number of values on line: " + Line + "\r\nin file: " + _FileName); // Remove leading / trailing double quote chars. for (int i = 0; i < words.Count; i++) words[i] = words[i].Trim("\"".ToCharArray()); return true; }
/// <summary> /// Reads the apsim header lines. /// </summary> /// <param name="inData">The in.</param> /// <param name="constantLines">The constant lines.</param> /// <param name="headingLines">The heading lines.</param> private void ReadApsimHeaderLines(StreamReaderRandomAccess inData, ref StringCollection constantLines, ref StringCollection headingLines) { string PreviousLine = ""; string Line = inData.ReadLine(); while (!inData.EndOfStream) { int PosEquals = Line.IndexOf('='); if (PosEquals != -1) { // constant found. constantLines.Add(Line); } else { if (IsCSVFile) { headingLines.Add(Line); break; } char[] whitespace = { ' ', '\t' }; int PosFirstNonBlankChar = StringUtilities.IndexNotOfAny(Line, whitespace); if (PosFirstNonBlankChar != -1 && Line[PosFirstNonBlankChar] == '(') { headingLines.Add(PreviousLine); headingLines.Add(Line); break; } } PreviousLine = Line; Line = inData.ReadLine(); } }