从流读取器读取一行而不消耗?

有没有办法提前读取一行来测试下一行是否包含特定的标签数据?

我正在处理一个具有开始标记但没有结束标记的格式。

我想读一行将它添加到一个结构然后测试下面的行,以确保它不是一个新的“节点”,如果它不是继续添加,如果它关闭该结构并创建一个新的

我能想到的唯一解决方案就是让两个流读取器同时出现在锁定步骤中的那种方式,但这看起来很浪费(如果它甚至可以工作)

我需要像peek但peekline这样的东西

您可以存储访问StreamReader.BaseStream.Position的位置,然后读取下一行的行,进行测试,然后在读取行之前找到该位置:

  // Peek at the next line long peekPos = reader.BaseStream.Position; string line = reader.ReadLine(); if (line.StartsWith("")) { // This is a new tag, so we reset the position reader.BaseStream.Seek(pos); } else { // This is part of the same node. } 

这是很多寻求和重读相同的路线。 使用某些逻辑,您可以完全避免这种情况 – 例如,当您看到新标记开始时,关闭现有结构并开始一个新结构 – 这是一个基本算法:

  SomeStructure myStructure = null; while (!reader.EndOfStream) { string currentLine = reader.ReadLine(); if (currentLine.StartsWith("")) { // Close out existing structure. if (myStructure != null) { // Close out the existing structure. } // Create a new structure and add this line. myStructure = new Structure(); // Append to myStructure. } else { // Add to the existing structure. if (myStructure != null) { // Append to existing myStructure } else { // This means the first line was not part of a structure. // Either handle this case, or throw an exception. } } } 

为什么这么难? 无论如何,返回下一行。 检查它是否是新节点,如果不是,则将其添加到结构中。 如果是,则创建一个新结构。

 // Not exactly C# but close enough Collection structs = new Collection(); Struct struct; while ((line = readline()) != null)) { if (IsNode(line)) { if (struct != null) structs.add(struct); struct = new Struct(); continue; } // Whatever processing you need to do struct.addLine(line); } structs.add(struct); // Add the last one to the collection // Use your structures here foreach s in structs { } 

这是我到目前为止所做的。 我通过直线路线比分流器更多地分开了路线。

我敢肯定,有一些地方正在消磨,因为它们更加优雅,但现在它似乎正在发挥作用。

请让我知道你在想什么

 struct INDI { public string ID; public string Name; public string Sex; public string BirthDay; public bool Dead; } struct FAM { public string FamID; public string type; public string IndiID; } List Individuals = new List(); List Family = new List(); private void button1_Click(object sender, EventArgs e) { string path = @"C:\mostrecent.ged"; ParseGedcom(path); } private void ParseGedcom(string path) { //Open path to GED file StreamReader SR = new StreamReader(path); //Read entire block and then plit on 0 @ for individuals and familys (no other info is needed for this instance) string[] Holder = SR.ReadToEnd().Replace("0 @", "\u0646").Split('\u0646'); //For each new cell in the holder array look for Individuals and familys foreach (string Node in Holder) { //Sub Split the string on the returns to get a true block of info string[] SubNode = Node.Replace("\r\n", "\r").Split('\r'); //If a individual is found if (SubNode[0].Contains("INDI")) { //Create new Structure INDI I = new INDI(); //Add the ID number and remove extra formating I.ID = SubNode[0].Replace("@", "").Replace(" INDI", "").Trim(); //Find the name remove extra formating for last name I.Name = SubNode[FindIndexinArray(SubNode, "NAME")].Replace("1 NAME", "").Replace("/", "").Trim(); //Find Sex and remove extra formating I.Sex = SubNode[FindIndexinArray(SubNode, "SEX")].Replace("1 SEX ", "").Trim(); //Deterine if there is a brithday -1 means no if (FindIndexinArray(SubNode, "1 BIRT ") != -1) { // add birthday to Struct I.BirthDay = SubNode[FindIndexinArray(SubNode, "1 BIRT ") + 1].Replace("2 DATE ", "").Trim(); } // deterimin if there is a death tag will return -1 if not found if (FindIndexinArray(SubNode, "1 DEAT ") != -1) { //convert Y or N to true or false ( defaults to False so no need to change unless Y is found. if (SubNode[FindIndexinArray(SubNode, "1 DEAT ")].Replace("1 DEAT ", "").Trim() == "Y") { //set death I.Dead = true; } } //add the Struct to the list for later use Individuals.Add(I); } // Start Family section else if (SubNode[0].Contains("FAM")) { //grab Fam id from node early on to keep from doing it over and over string FamID = SubNode[0].Replace("@ FAM", ""); // Multiple children can exist for each family so this section had to be a bit more dynaimic // Look at each line of node foreach (string Line in SubNode) { // If node is HUSB if (Line.Contains("1 HUSB ")) { FAM F = new FAM(); F.FamID = FamID; F.type = "PAR"; F.IndiID = Line.Replace("1 HUSB ", "").Replace("@","").Trim(); Family.Add(F); } //If node for Wife else if (Line.Contains("1 WIFE ")) { FAM F = new FAM(); F.FamID = FamID; F.type = "PAR"; F.IndiID = Line.Replace("1 WIFE ", "").Replace("@", "").Trim(); Family.Add(F); } //if node for multi children else if (Line.Contains("1 CHIL ")) { FAM F = new FAM(); F.FamID = FamID; F.type = "CHIL"; F.IndiID = Line.Replace("1 CHIL ", "").Replace("@", ""); Family.Add(F); } } } } } private int FindIndexinArray(string[] Arr, string search) { int Val = -1; for (int i = 0; i < Arr.Length; i++) { if (Arr[i].Contains(search)) { Val = i; } } return Val; }