jeffers
jeffers

Reputation: 145

How to read text from file from one value to other in c#

I`m new in c#, I'm still learning that language. Now I try to make app which read text and to my data i need only specific lines. Text look like:

[HAEDING]
Some value

[HEADING]
Some other value

[HEADING]
Some other text
and continuation of this text in new line

[HEADING]
Last text

I try to write method which read text and put it into string[] by split it like this:

string[0] = Some value
string[1] = Some other value
string[2] = Some other text and continuation of this text in new line
string[3] = Last text

So I want to read line from value [HEADING] to value new line which is empty. I thought that is should write by ReadAllLines and line by line check start position on value [HEADING] and end position on empty value in new line. I try this code:

string s = "mystring";
int start = s.IndexOf("[HEADING]");
int end = s.IndexOf("\n", start);
string result = s.Substring(start, end - start);

but it's substring to all lines in my text not like loop between first [HEADING] and empty new line, second etc. Maybe someone can help me with this?

Upvotes: 0

Views: 79

Answers (3)

Kit
Kit

Reputation: 21739

Here's a solution which avoids the substring/index checking, which could potentially be fraught with errors.

There are answers such as this one that use LINQ, but for a newcomer to the language, basic looping is an OK place to start. Also, this is not necessarily the best solution for efficiency or whatever.

This foreach loop will handle your case, and some of the "dirty" cases.

var segments = new List<string>();
bool headingChanged = false;
foreach (var line in File.ReadAllLines("somefilename.txt"))
{
    // skip blank lines
    if (string.IsNullOrWhitespace(line)) continue;

    // detect a heading
    if (line.Contains("[HEADING]")
    {
        headingChanged = true;
        continue;
    }

    if (headingChanged)
    {
        segments.Add(line);

        // this keeps us working on the same segment if there
        // are more lines to be added to the segment
        headingChanged = false;
    }
    else
    {
        segments[segments.Length - 1] += " ";
        segments[segments.Length - 1] += line;
        // you could replace the above two lines with string interpolation...
        // segments[segments.Length - 1] = $"{segments[segments.Length - 1]} {line}";
    }
}

In the above loop, the ReadAllLines obviates the need to check for \r and \n. Contains will handle [HEADING] no matter where it changes.

Upvotes: 2

Yair Maron
Yair Maron

Reputation: 1958

You don't need substring, you can just compare the value s == "[HEADING]".

Here's an easy to understand example:

var lines = System.IO.File.ReadAllLines(myFilePath);

var resultLines = new List<String>();

var collectedText = new List<String>();

foreach (var line in lines)
{
    if (line == "[HEADING]")
    {
        collectedText = new List<String>();
    }
    else if (line != "")
    {
        collectedText.Add(line);
    }
    else //if (line == "")
    {
        var joinedText = String.Join(" ", collectedText);
        resultLines.Add(joinedText);
    }
}

return resultLines.ToArray();

the loop does this:

  1. we go line by line
  2. "start collecting" (create list) when we encounter with "[HEADING]" line
  3. "collect" (add to list) line if not empty
  4. "finish collecting" (concat and add to results list) when line is empty

Upvotes: 1

Stephan Bauer
Stephan Bauer

Reputation: 9249

You could try to split the string by "[HEADING]" to get the strings between these lines. Then you could join each string into a single line and trim the whitespace around the strings:

string content = @"[HEADING]
Some value

[HEADING]
Some other value

[HEADING]
Some other text
and continuation of this text in new line

[HEADING]
Last text";

var segments = content.Split(new[] { "[HEADING]"}, StringSplitOptions.RemoveEmptyEntries)  // Split into multiple strings
    .Select(p=>p.Replace("\r\n"," ").Replace("\r"," ").Replace("\n"," ").Trim()) // Join each single string into single line
    .ToArray();

Result:

segments[0] = "Some value"
segments[1] = "Some other value"
segments[2] = "Some other text and continuation of this text in new line"
segments[3] = "Last text" 

Upvotes: 5

Related Questions