Click here to Skip to main content
15,867,330 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello All,

I have file called the LittleStory.txt. I have an identifier at the start (//gotostart) and end (//gotoend) of a section that I would like to be able to extract and put it in another file.


LittleStory.txt
Line1
Line2
Line3
Line4
//gotostart
Line6
Line7
Line8
//gotoend
Line10
Line11
Line12

I'm able to pull the line numbers from the txt file using:
int gotostartlineNumber = gotostartcounter;
int gotoendlineNumber = gotoendcounter;


 public void getgotostartlinenumber()
{
	System.IO.StreamReader gotostartfile = new System.IO.StreamReader("c:\\temp\\LittleStory.txt");
	while ((gotostartline = gotostartfile.ReadLine()) != null) 
	{
		if (gotostartline.Contains("//gotostart")) // #Requirements
		{
			Console.WriteLine(gotostartcounter.ToString() + ": " + gotostartline);
		}
		gotostartcounter++;
	}
	gotostartfile.Close();
}

public void getgotoendlinenumber()
{
	System.IO.StreamReader gotoendfile = new System.IO.StreamReader("c:\\temp\\LittleStory.txt");
	while ((gotoendline = gotoendfile.ReadLine()) != null)
	{
		if (gotoendline.Contains("//gotoend")) // #Requirements
		{
			Console.WriteLine(gotoendcounter.ToString() + ": " + gotoendline);
		}

		gotoendcounter++;
	}

	gotoendfile.Close();
}


What gets returned is
//gotostart = 5
//gotoend = 9

I want to be able to extract the lines in-between 5 and 9 which would be
Line6
Line7
Line8

and then put them in a file call NewFile.txt.

Any help would be much appreciated.

Thanks

What I have tried:

I tried using LINQ and StreamReader and I'm stuck.

I tried this
var data = File.ReadAllLines(fileName)
                .Skip(gotostartlineNumber)
                .Take(gotoendlineNumber)
                .ToArray();

Console.WriteLine(data.ToString());


This failed.

Also tried many variations of StreamReader
try
{
	if (File.Exists(filePath))
	{
		using (StreamReader _StreamReader = new StreamReader(filePath))
		{
			for (int a = gotostartlineNumber; a <= gotoendlineNumber; a++)
			{
				result = _StreamReader.ReadLine();
			}
		}
	}
}
catch { }
//return result;
Console.WriteLine(result);


This only returns 1 line.
Posted
Updated 9-Oct-21 1:33am
Comments
PIEBALDconsult 8-Oct-21 8:28am    
Regular Expressions.

1) Read all the liens into an array
2) Create a boolean: foundStart and set it to false.
3) Loop through all lines in the array.
3.1) If foundStart is not true, use string.StartsWith to compare it with your "start of text" indicator.
3.1.1) If it finds it, set foudStart to true
3.1.2) Otherwise, ignore the line
3.2) Otherwise, use string.StartsWith to compare it with your "end of text" indicator.
3.2.1) If it finds it, use break to exit the loop.
3.2.2) Otherwise, add the line to the output file.

Done!
 
Share this answer
 

My suggestion is to simply extract the required lines as a substring and save that to a file.

C#
string txt = File.ReadAllText(@"c:\temp\LittleStory.txt");
string startMarker = "//gotostart\r\n";
string endMarker = "//gotoend";
int startIndex = txt.IndexOf(startMarker) + startMarker.Length;
int endIndex = txt.IndexOf(endMarker);
string textToSave = txt.Substring(startIndex, endIndex - startIndex);
File.WriteAllText(@"C:\temp\LittleStoryExtract.txt", textToSave);
//To read back the text use
string[] lines = File.ReadAllLines(@"C:\temp\LittleStoryExtract.txt");
foreach(var l in lines)
{
    Console.WriteLine(l);
}

 
Share this answer
 
v2
Comments
Member 15386332 8-Oct-21 7:56am    
Thanks George, it works; however, something I noticed. I have something that looks like this
(whitespace)Line6
(tab)Line7
(tab)(tab)Line8
How do I remove the tabs? When I put .trim in every place I'm only able to remove the tabs or whitespace on the first line. How do I remove the tabs or leading whitespace on all the lines to look like this?
Line6
Line7
Line8

Thanks
George Swan 8-Oct-21 10:19am    
I have updated my code to show how to read back the text. Does that solve your problem?
Member 15386332 11-Oct-21 0:59am    
Hello George,
I got your code to work, thanks. I had to modify it a little because I still wasn't getting a left justification or trimming the beginning white space. Here's what I did to modify it.
To just output it:
Console.WriteLine(l.Trim());

I had to do something different when writing to a file.
File.AppendAllText(@"C:\temp\LittleStoryExtractAgain.txt",l.Trim() + "\n");

Thoughts on a better way to put it to a file?

Thanks
George Swan 11-Oct-21 1:54am    
I found the following example to be helpful
https://docs.microsoft.com/en-us/troubleshoot/dotnet/csharp/read-write-text-file
Another exanple;
public List<string> GetFlaggedSection(string filepath, string startflag, string endflag)
{
    using (System.IO.StreamReader thefile = new System.IO.StreamReader(filepath))
    {
        string currentline;
    
        List<string> selectedlines = null;
    
        bool startlineseen = false;
    
        while ((currentline = thefile.ReadLine()) != null)
        {
            if (currentline.ToLower() == startflag)
            {
                selectedlines = new List<string>();
                startlineseen = true;
            }
            else if (currentline.ToLower() == endflag)
            {
                break;
            }
            else if (startlineseen)
            {
                selectedlines.Add(currentline);
            }
        }
    
        thefile.Close();
    
        return selectedlines;
    }
}
Note:

1) use a 'using statement ... if you are not familiar with that, look it up

2) for production code: implement checking the file path is valid; clean lines even more than just making them lower-case as shown here; anticipate possible format errors like more than one, or none, "startflag" and throw appropriate errors.

3) Because of the possible complexity of flaws in the source file: look at using a higher level file with innate structure, like JSON.

To use this in a Console App:
class Program
{
    static void Main(string[] args)
    {
       string path = Console.ReadLine();

       // you should validate path here

       lines = GetFlaggedSection(path, "//gotostart", "//gotoend");

       foreach (string  line in lines)
       {
           Console.WriteLine(line);
       }

       Console.ReadKey();
    }

    static List<string> lines = new List<string>();

    static List<string> GetFlaggedSection(string filepath, string startflag, string endflag)
    }
}
'lines and 'GetFlaggedSection must be declared static because they are used in a static context.
 
Share this answer
 
v5
Comments
Member 15386332 11-Oct-21 0:47am    
Hello Bill,

You've got me stumped. I've been looking it up. I don't know how to call a List<string> in the static void Main(string[] args). I understand that I need a filepath, startflag and endflag. I know exactly what I want to pass but how?
BillWoodruff 11-Oct-21 2:37am    
A few changes are necessary to use this in a Console App, I've added a "how-to" to my solution.
Member 15386332 20-Oct-21 23:37pm    
Thanks, I got it to work and integrated it with some other code. Much Appreciated
First step: combine both functions into one
C#
public void getlinenumbers() {
	System.IO.StreamReader gotostartfile = new System.IO.StreamReader("c:\\temp\\LittleStory.txt");
	while ((gotostartline = gotostartfile.ReadLine()) != null) 
	{
		if (gotostartline.Contains("//gotostart")) // #Requirements
		{
			Console.WriteLine(gotostartcounter.ToString() + ": " + gotostartline);
		}
		if (gotostartline.Contains("//gotoend")) // #Requirements
		{
			Console.WriteLine(gotostartcounter.ToString() + ": " + gotostartline);
		}
		gotostartcounter++;
	}
	gotostartfile.Close();
}

Then add code to print lines between start and end (after detecting start and before detecting end)
 
Share this answer
 
v4
Comments
BillWoodruff 9-Oct-21 7:49am    
vote of #1: you have never tested this; errors are obvious.
Patrice T 9-Oct-21 7:55am    
Better that way ?
Member 15386332 20-Oct-21 23:38pm    
Thanks for your code too. I was actually able to use your code with something else. Much Appreciated.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900