C# StringBuilder: Check if it ends with a new line
Asked Answered
L

7

9

I have a StringBuilder that accumulates code. In some cases, it has 2 empty lines between code blocks, and I'd like to make that 1 empty line.
How can I check if the current code already has an empty line at the end? (I prefer not to use its ToString() method because of performance issues.)

Loutitia answered 27/12, 2012 at 12:7 Comment(3)
You will either have to check the lines/blocks as you add them - or replace all "double new lines" with a single one, and trim the end.Kenogenesis
Could use Replace and replace any occurrence of two Environment.NewLine with a single Environment.NewLine (this at the end of the building). another possibility is ToString(length-1,1) to get the final character.Heterochromous
This is what I did eventually. It was posted as answer but was deleted because someone mentioned that it will also remove double new lines in the middle of the code. It really doesn't matter to me, so if this solution will be posted as an answer, I'll mark it.Loutitia
L
-1

Since I don't care about 2 empty lines in the middle of the code, the simplest way is to use

myCode.Replace(string.Format("{0}{0}", Environment.NewLine),Environment.NewLine);

This option doesn't require any changes to classes that use the code accumulator.

Loutitia answered 31/12, 2012 at 7:36 Comment(2)
That won't work if myCode doesn't use Environment.NewLine as its line separator. Also, this is not more efficient that ToString.Swanhilda
Even if this seems to work for your particular situation, this is not an answer to the question you've put down.Paralogism
R
7

You can access any character of your StringBuilder with its index, like you would with a String.

var sb = new StringBuilder();
sb.Append("Hello world!\n");
Console.WriteLine(sb[sb.Length - 1] == '\n'); // True
Residentiary answered 27/12, 2012 at 12:12 Comment(2)
I'm talking about huge code chunks. I tried checking the finishing characters but it got messy.Loutitia
Why did it got messy? If you write a method that accepts a StringBuilder then you can create a neat little subroutine. Divide and conquer. Note that this works for Linux and Windows, but not for Mac line endings prior to Mac OSX, which ends with \r (but that's easy to program, and yeah, prehistoric).Paralogism
S
2

I've got 'funny' answer:

var sb = new StringBuilder();
sb.AppendLine("test");
sb.AppendLine("test2");

Console.WriteLine(sb.ToString().TrimEnd('\n').Length != sb.ToString().Length); //true
Steelmaker answered 13/1, 2023 at 12:0 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Zara
K
1

You can normalize the newlines, using a regex:

var test = @"hello

moop

hello";

var regex = new Regex(@"(?:\r\n|[\r\n])+");

var newLinesNormalized = regex.Replace(test, Environment.NewLine);

output:

hello
moop
hello
Kenogenesis answered 27/12, 2012 at 12:18 Comment(1)
How is this related to StringBuilder?Swanhilda
D
1

Single line check. Uses a string type, not StringBuilder, but you should get the basic idea.

if (theString.Substring(theString.Length - Environment.NewLine.Length, Environment.NewLine.Length).Contains(Environment.NewLine))
{
     //theString does end with a NewLine
}
else
{
     //theString does NOT end with a NewLine
}
Diurnal answered 21/8, 2014 at 8:46 Comment(3)
This of course only works for the platform default line ending, which could be a bit presumptuous. It also doesn't use StringBuilder it seems.Paralogism
@MaartenBodewes Platform detection wasn't a requirement and I literally said in the opening line that it doesn't use StringBuilder. Upon rereading the original issue I am not sure it even addresses his problem - does he want to check if there are extra linebreaks at the end of the whole string or does he want to analyse each "line" in the string and remove double linebreaks...Diurnal
Of course questions are written by a specific user, but they should be applicable for other users. If this only works for platform encoding then at least state that in the answer, or everybody that copies your code may run into problems. The question explicitly states that strings should preferably not be used - but besides that the question would be much less useful to others if strings can be used; that's an easier question to solve (regex etc.). Thanks for taking another look though.Paralogism
C
0

Here is the complete example.

class string_builder
{
    string previousvalue = null;
    StringBuilder sB;
    public string_builder()
    {
        sB = new StringBuilder();
    }
    public void AppendToStringBuilder(string new_val)
    {
        if (previousvalue.EndsWith("\n") &&  !String.IsNullOrEmpty(previousvalue) )
        {
            sB.Append(new_val);
        }
        else
        {
            sB.AppendLine(new_val);
        }

        previousvalue = new_val;
    }

}
class Program
{

    public static void Main(string[] args)
    {
        string_builder sb = new string_builder();            
        sb.AppendToStringBuilder("this is line1\n");
        sb.AppendToStringBuilder("this is line2");
        sb.AppendToStringBuilder("\nthis is line3\n");

    }            
}
Catanddog answered 27/12, 2012 at 13:24 Comment(2)
This will require a huge change in my code - I wish to keep the changes to minimum. Thanks for the code sample though.Loutitia
This is a code only example that doesn't answer the question in the title.Paralogism
L
-1

Since I don't care about 2 empty lines in the middle of the code, the simplest way is to use

myCode.Replace(string.Format("{0}{0}", Environment.NewLine),Environment.NewLine);

This option doesn't require any changes to classes that use the code accumulator.

Loutitia answered 31/12, 2012 at 7:36 Comment(2)
That won't work if myCode doesn't use Environment.NewLine as its line separator. Also, this is not more efficient that ToString.Swanhilda
Even if this seems to work for your particular situation, this is not an answer to the question you've put down.Paralogism
A
-1

In-case anyone ends up here like I did here is a general method to check the end of a StringBuilder for an arbitrary string with having to use ToString on it.

public static bool EndsWith(this StringBuilder haystack, string needle)
{
    var needleLength = needle.Length - 1;
    var haystackLength = haystack.Length - 1;
    if (haystackLength < needleLength)
    {
        return false;
    }
    for (int i = 0; i < needleLength; i++)
    {
        if (haystack[haystackLength - i] != needle[needleLength - i])
        {
            return false;
        }
    }
    return true;
}
Amaranth answered 1/11, 2013 at 7:21 Comment(1)
There may be more than a single line ending possible, and your needle only accepts one string.Paralogism

© 2022 - 2024 — McMap. All rights reserved.