private string LookAheadForNonMissingValue(StreamReaderRandomAccess In, int w) { if (In.EndOfStream) { return("?"); } int Pos = In.Position; StringCollection Words = new StringCollection(); while (GetNextLine(In, ref Words) && Words[w] == "?") { ; } In.Position = Pos; if (Words.Count > w) { return(Words[w]); } else { return("?"); } }
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); } } }
public void TestPositionAfterSeek(string input, int seekPosition, SeekOrigin origin, int expectedPosition) { using (Stream stream = CreateStream(input)) { StreamReaderRandomAccess reader = new StreamReaderRandomAccess(stream); reader.Seek(seekPosition, SeekOrigin.Begin); Assert.AreEqual(expectedPosition, reader.Position); } }
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> /// Determine and return the data types of the specfied words. /// </summary> private Type[] DetermineColumnTypes(StreamReaderRandomAccess In, StringCollection Words) { Type[] Types = new Type[Words.Count]; for (int w = 0; w != Words.Count; w++) { if (Words[w] == "?" || Words[w] == "*" || Words[w] == "") { Types[w] = StringManip.DetermineType(LookAheadForNonMissingValue(In, w), Units[w]); } else { Types[w] = StringManip.DetermineType(Words[w], Units[w]); } } return(Types); }
/// <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); }
/// <summary> /// Read in the APSIM header - headings/units and constants. /// </summary> private void ReadApsimHeader(StreamReaderRandomAccess In) { StringCollection ConstantLines = new StringCollection(); StringCollection HeadingLines = new StringCollection(); ReadApsimHeaderLines(In, ref ConstantLines, ref HeadingLines); bool TitleFound = false; foreach (string ConstantLine in ConstantLines) { string Line = ConstantLine; string Comment = StringManip.SplitOffAfterDelimiter(ref Line, "!"); Comment.Trim(); int PosEquals = Line.IndexOf('='); if (PosEquals != -1) { string Name = Line.Substring(0, PosEquals).Trim(); if (Name.ToLower() == "title") { TitleFound = true; Name = "Title"; } string Value = Line.Substring(PosEquals + 1).Trim(); string Unit = StringManip.SplitOffBracketedValue(ref Value, '(', ')'); _Constants.Add(new APSIMConstant(Name, Value, Unit, Comment)); } } if (HeadingLines.Count >= 2) { if (CSV) { HeadingLines[0] = HeadingLines[0].TrimEnd(','); HeadingLines[1] = HeadingLines[1].TrimEnd(','); Headings = new StringCollection(); Units = new StringCollection(); Headings.AddRange(HeadingLines[0].Split(",".ToCharArray())); Units.AddRange(HeadingLines[1].Split(",".ToCharArray())); for (int i = 0; i < Headings.Count; i++) { Headings[i] = Headings[i].Trim(); } for (int i = 0; i < Units.Count; i++) { Units[i] = Units[i].Trim(); } } else { Headings = StringManip.SplitStringHonouringQuotes(HeadingLines[0], " \t"); Units = StringManip.SplitStringHonouringQuotes(HeadingLines[1], " \t"); } TitleFound = TitleFound || StringManip.IndexOfCaseInsensitive(Headings, "title") != -1; if (Headings.Count != Units.Count) { throw new Exception("The number of headings and units doesn't match in file: " + _FileName); } } if (!TitleFound) { _Constants.Add(new APSIMConstant("Title", Path.GetFileNameWithoutExtension(_FileName), "", "")); } }