private void ReadApsimHeaderLines(StreamReaderRandomAccess In, ref StringCollection ConstantLines, ref StringCollection HeadingLines) { string PreviousLine = ""; string Line = In.ReadLine(); while (Line != "" || !In.EndOfStream) { int PosEquals = Line.IndexOf('='); if (PosEquals != -1) { // constant found. ConstantLines.Add(Line); } else { char[] whitespace = { ' ', '\t' }; int PosFirstNonBlankChar = StringManip.IndexNotOfAny(Line, whitespace); if (PosFirstNonBlankChar != -1 && Line[PosFirstNonBlankChar] == '(') { HeadingLines.Add(PreviousLine); HeadingLines.Add(Line); break; } } PreviousLine = Line; Line = In.ReadLine(); } }
public void TestBomParsing(string inputFile) { string[] expected = new string[4] { "x,y", "0,1", "1,2", "2,4" }; long[] endOfLinePositions = new long[expected.Length]; using (Stream stream = GetResourceStream(inputFile)) { StreamReaderRandomAccess reader = new StreamReaderRandomAccess(stream); for (int i = 0; i < expected.Length; i++) { string line = reader.ReadLine(); Assert.AreEqual(expected[i], line); endOfLinePositions[i] = reader.Position; } // Seek to the end of each line, and read a line, and ensure // that we get the expected result. This should probably be a // separate test. for (int i = 1; i < expected.Length - 1; i++) { reader.Seek(endOfLinePositions[i], SeekOrigin.Begin); string input = reader.ReadLine(); Assert.AreEqual(expected[i + 1], input); } } }
/// <summary> /// Seek to the specified date. Will throw if date not found. /// </summary> /// <param name="Date"></param> public void SeekToDate(DateTime Date) { int NumRowsToSkip = (Date - _FirstDate).Days; In.Seek(FirstLinePosition, SeekOrigin.Begin); while (!In.EndOfStream && NumRowsToSkip > 0) { In.ReadLine(); NumRowsToSkip--; } int SavedPosition = In.Position; StringCollection Words = new StringCollection(); if (GetNextLine(In, ref Words)) { // Make sure we found the date. object[] Values = ConvertWordsToObjects(Words, ColumnTypes); DateTime RowDate = GetDateFromValues(Values); if (RowDate != Date) { throw new Exception("Non consecutive dates found in file: " + _FileName); } } else { throw new Exception("End of file reached while trying to find date " + Date.ToShortDateString() + " in file " + _FileName); } // All ok - restore position. In.Seek(SavedPosition, SeekOrigin.Begin); }
public void TestPositionAfterRead(string input, int expectedPosition) { using (Stream stream = CreateStream(input)) { StreamReaderRandomAccess reader = new StreamReaderRandomAccess(stream); reader.ReadLine(); Assert.AreEqual(expectedPosition, reader.Position); } }
/// <summary> /// Open the file ready for reading. /// </summary> public void Open(string FileName) { if (FileName == "") { return; } if (!File.Exists(FileName)) { throw new Exception("Cannot find file: " + FileName); } _FileName = FileName; CSV = Path.GetExtension(FileName).ToLower() == ".csv"; _Constants.Clear(); In = new StreamReaderRandomAccess(_FileName); ReadApsimHeader(In); FirstLinePosition = In.Position; // Read in first line. StringCollection Words = new StringCollection(); GetNextLine(In, ref Words); ColumnTypes = DetermineColumnTypes(In, Words); // Get first date. object[] Values = ConvertWordsToObjects(Words, ColumnTypes); _FirstDate = GetDateFromValues(Values); // Now we need to seek to the end of file and find the last full line in the file. In.Seek(0, SeekOrigin.End); if (In.Position >= 1000 && In.Position - 1000 > FirstLinePosition) { In.Seek(-1000, SeekOrigin.End); In.ReadLine(); // throw away partial line. } else { In.Seek(FirstLinePosition, SeekOrigin.Begin); } while (GetNextLine(In, ref Words)) { } In.Seek(FirstLinePosition, SeekOrigin.Begin); // 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); }
public void TestSeek(string input, int position, SeekOrigin origin, string expectedOutput) { using (Stream stream = CreateStream(input)) { StreamReaderRandomAccess reader = new StreamReaderRandomAccess(stream); reader.Seek(position, origin); string actualOutput = reader.ReadLine(); Assert.AreEqual(expectedOutput, actualOutput); } }
public void TestReadLine(string input, params string[] expectedOutputs) { using (Stream stream = CreateStream(input)) { StreamReaderRandomAccess reader = new StreamReaderRandomAccess(stream); for (int i = 0; i < expectedOutputs.Length; i++) { Assert.AreEqual(expectedOutputs[i], reader.ReadLine()); } } }
/// <summary> /// Return the next line in the file as a collection of words. /// </summary> private bool GetNextLine(StreamReaderRandomAccess In, ref StringCollection Words) { if (In.EndOfStream) { return(false); } string Line = In.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 (CSV) { Words.Clear(); Line = Line.TrimEnd(','); Words.AddRange(Line.Split(",".ToCharArray())); } else { Words = StringManip.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); }