قراءة الخط من streamreader دون استهلاك؟
-
20-08-2019 - |
سؤال
هل هناك طريقة لقراءة قبل سطر واحد لاختبار إذا السطر التالي يحتوي على بيانات بطاقة معينة؟
وأتعامل مع شكل الذي يحتوي على وسم البداية ولكن لا وسم النهاية.
وأود أن قراءة سطر إضافته إلى الهيكل ثم اختبار خط أدناه للتأكد من أنها ليست "عقدة" جديدة وإذا لم يتم الحفاظ على إضافة ما اذا كان على مقربة من أن البنية وجعل واحدة جديدة
والحل الوحيد الذي يمكنني أن أفكر فيه هو أن يكون اثنين من القراء تيار الذهاب في نفس الوقت suffling كيندا هناك طريقة جنبا إلى جنب خطوة القفل ولكن يبدو أن wastefull (اذا كانت ستعمل حتى)
وأحتاج شيئا مثل نظرة خاطفة ولكن peekline
المحلول
والمشكلة هي الدفق الأساسي قد لا تكون حتى seekable. إذا كنت نلقي نظرة على تنفيذ تيار القارئ أنه يستخدم عازلة بحيث يمكن تنفيذ TextReader.Peek () حتى لو كان تيار ليس seekable.
هل يمكن كتابة محول بسيط هو أن يقرأ السطر التالي ومخازن داخليا، شيء من هذا القبيل:
public class PeekableStreamReaderAdapter
{
private StreamReader Underlying;
private Queue<string> BufferedLines;
public PeekableStreamReaderAdapter(StreamReader underlying)
{
Underlying = underlying;
BufferedLines = new Queue<string>();
}
public string PeekLine()
{
string line = Underlying.ReadLine();
if (line == null)
return null;
BufferedLines.Enqueue(line);
return line;
}
public string ReadLine()
{
if (BufferedLines.Count > 0)
return BufferedLines.Dequeue();
return Underlying.ReadLine();
}
}
نصائح أخرى
هل يمكن تخزين موقف الوصول إلى StreamReader.BaseStream.Position، ثم قراءة السطر التالي خط، هل اختبار الخاص بك، ثم السعي إلى موقف قبل أن تقرأ السطر:
// Peek at the next line
long peekPos = reader.BaseStream.Position;
string line = reader.ReadLine();
if (line.StartsWith("<tag start>"))
{
// 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("<tag start>"))
{
// 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 {
}
وهنا هو ما أذهب حتى الآن. ذهبت أكثر من مسار الانقسام من خط streamreader من طريق الخط.
وأنا متأكد من أن هناك عدد قليل من الأماكن التي يتم يموتون لتكون أكثر أناقة ولكن لفي الوقت الراهن يبدو أن العمل.
واسمحوا لي أن أعرف ما هو رأيك
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<INDI> Individuals = new List<INDI>();
List<FAM> Family = new List<FAM>();
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;
}