1

I'm newbie in C# so please go easy on me... basically, I'm reading through a text file and want to grab any data between two strings and store all of this data into a string / variable - how would I go about doing this?

I've already got the below but just need a push in the right direction to get me back on track.

Many Thanks

C# Code:

bool DetailsFound = false;
string[] ReadLines = File.ReadAllLines(path);
foreach (string item in ReadLines) {
    if (item == "Start Details") {
        DetailsFound = true;
    }
    if (DetailsFound) {
        Console.WriteLine("Details - " + item);
        // VARIABLE / STRING REQUIRED HERE
    }
    if (item == "End Details") {
        break;
    }
}

Example *.TXT File

Start Details
I am line 1
I am line 2
I am line 3
End Details
12
  • 2
    You should use lower camel case for variable names; so detailsFound rather than DetailsFound Commented Jan 24, 2018 at 12:35
  • So would your expected output be the contents of the file minus the Start Details and End Details lines? Commented Jan 24, 2018 at 12:36
  • 1
    Looks like a job for List<String>. Commented Jan 24, 2018 at 12:36
  • Declare string strAllLine = string.Empty; then in if loop if (DetailsFound) { Console.WriteLine("Details - " + item); strAllLine = strAllLine + item; } so all the Line value will be stored in strAllLine string. Commented Jan 24, 2018 at 12:38
  • 2
    @user3501749 Don't do that. Commented Jan 24, 2018 at 12:39

7 Answers 7

3

You need to do everything in the correct order.
Use something like StringBuilder to store the strings.

var detailsFound = false;
var readLines = File.ReadAllLines(path);
var stringB = new StringBuilder();
foreach (string item in readLines) {
    if (item == "Start Details") {
        detailsFound = true;
    }
    else if (item == "End Details") {
        break;
    }
    else if (detailsFound) {
        Console.WriteLine("Details - " + item);
        stringB.AppendLine(item);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

First, you need to fix your logic to handle the end correctly (it's a matter of execution order).

Then, use a StringBuilder to concatenate the strings:

StringBuilder sb = new StringBuilder();

foreach (string item in ReadLines) {
    if (item == "Start Details") {
        DetailsFound = true;
    }
    else if (item == "End Details") {
        break;
    }
    else if (DetailsFound) {
        Console.WriteLine("Details - " + item);
        sb.AppendLine(item);
        // VARIABLE / STRING REQUIRED HERE
    }
}

string output = sb.ToString();

If you want to have the lines a separate values, use a List<string>:

List<string> list = new List<string>();

foreach (string item in ReadLines) {
    if (item == "Start Details") {
        DetailsFound = true;
    }
    else if (item == "End Details") {
        break;
    }
    else if (DetailsFound) {
        Console.WriteLine("Details - " + item);
        list.Add(item);
        // VARIABLE / STRING REQUIRED HERE
    }
}

// list holds all lines

Comments

1

Few comments:

  • You should look at MSDN for General Naming Conventions
  • Using File.ReadAllLines will load all the lines in the file to memory. In this instance, I don't think we want to do it as we may stop after several lines. Consider using File.ReadLines

You were given plenty of answers that use the usual enumeration, which is great for a C# beginner as it should look familiar to other languages. I want to expose you to one powerful C# feature, LINQ.

You can perform the task in the following manner:

    public static void TakeBetween(string filePath, string startText, string endText)
    {
        var data = File.ReadLines(filePath).SkipWhile(line => !line.Contains(startText)).Skip(1).TakeWhile(line => !line.Contains(endText));
        // Do whatever that is needed with data. It is of type IEnumerable<string>
    }

you can replace .Contains with any other string finding method you desire. Note that this won't load unnecessary data to memory.

Relevant LINQ functions:

1 Comment

Thanks Eylon - I will take a read through the links you provided.
0

You're not too far off.

With a few minor modifications to your code:

List<string> results = new List<string>();

foreach (string item in ReadLines) 
{
    if (item == "Start Details") 
    {
        DetailsFound = true;
    }
    else if (item == "End Details") {
        break;
    }
    else if (DetailsFound) 
    {
        Console.WriteLine("Details - " + item);
        results.Add(item);
    }

}

That will store the strings found in a list. Now you can process them as you wish. For instance, you can get them all together in a single comma-separated string:

var commaSeparated = String.Join(results, ", ");

Comments

0

Try following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;


namespace Oppgave3Lesson1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.txt";
        static void Main(string[] args)
        {
            string input = "";
            List<string> lines = new List<string>();
            StreamReader reader = new StreamReader(FILENAME);

            Boolean foundStart = false;
            while ((input = reader.ReadLine()) != null)
            {
                if (!foundStart)
                {
                    if(input.StartsWith("Start")) foundStart = true;
                }
                else
                {
                    if (input.StartsWith("End")) break;
                    lines.Add(input);
                }
            }

        }
    }
}

Comments

0

item is defined in the foreach loop and refers to the read line. You must define before the loop a string variable and attach each item.

string WriteDataHere = String.Empty; // <- 

bool DetailsFound = false;
string[] ReadLines = File.ReadAllLines(path);
foreach (string item in ReadLines) {
    if (item == "Start Details") {
    DetailsFound = true;
}
if (DetailsFound) {
    Console.WriteLine("Details - " + item);
    // VARIABLE / STRING REQUIRED HERE
    WriteDataHere += item; // <--
    }
    if (item == "End Details") {
        break;
    }
}

But this solution would cause a string that looks like this:

I am line 1I am line 2I am line 3

A possible solution is to check if this string is empty and add a linebreak if notso the code line looks a little bit different:

if( String.isNullOrEmpty(WriteDataHere) == false)
   WriteDataHere += "\n";

WriteDataHere += item; // <--

A little bit better solution is to save all "items" in a List

List<string> listOfStrings = new List<string>();

and add each item on each iteration via the Add-Method.

But it depends on what you plan to do with your string.

2 Comments

Never use string concatenation in a tight loop.
Can you explain why I never should use it and what a tight loop is? I'm interested in the background of this statement.
0

If you are wanting to output the lines after some specific string, I'd do it like this

const string _startIdentifier = "Start Details"
const string _endIdentifier = "End Details"

private bool detailsFound
private List<string> details

foreach (string item in File.ReadAllLines(path)) {
    if (!detailsFound && item.Equals(_startIdentifier) {
        detailsFound = true;
    }

    if (item.Equals(__endIdentifier){
        break;
    }

    if (detailsFound) {
        details.Add(item);
        Console.WriteLine("Details - " + item);
    }
}

Then if you want to combine those items into a single string

var combinedItems = String.Join(", ", items)

That will create a string that looks something like "I am line 1, I am line 2, I am line 3". Of course you can change the deliminator from a comma to a new line with Environment.NewLine

1 Comment

Edited my answer @PatrickHofman. Not sure if by 'store' the OP means in memory (as a list like I'm using) or as a single string (in which case Sani's string builder solution is probably better)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.