views:

192

answers:

10

I have a StringBuilder instance where I am doing numerous sb.AppendLine("test"); for example.

How do I work out how many lines I have?

I see the class has .Length but that tells me how many characters in all.

Any ideas?

+1  A: 

You should be able to search for the number of occurences of \n in the string.

UPDATE: One way could be to split on the newline character and count the number of elements in the array as follows:

sb.ToString().Split('\n').length;
Paul Hadfield
Will surely work but not a good solution if you need line count repeatedly. Of course, Jon hasn't mentioned if he wants it one time or many times.
VinayC
@VninayC - yes, it was an idea off the top of my head on how to do it, I didn't like it from the outset as you've got to do a ToString() to do anything at all. Definitely if you wanted to do it multiple times wrapping it up in something that kept a count itself would be best.
Paul Hadfield
+6  A: 

You could wrap StringBuilder with your own class that would keep a count of lines as they are added or could the number of '\n' after your builder is full.

Regex.Match(builder.ToString(), Environment.NewLine).Length
Jake Pearson
+1 own class, or maybe even an extension method.
sixlettervariables
A: 

Do a regex to count the number of line terminators (ex: \r\n) in the string. Or, load the strings into a text box and do a line count but thats the hack-ey way of doing it

Ayubinator
+3  A: 

Try this:

sb.ToString().Split(System.Environment.NewLine.ToCharArray()).Length;
Bravax
Umm... this code double-counts the lines... for example 3 lines of sb.AppendLine("a"); will result in 7, not 3...!
code4life
A: 

You can split string bulider data into String[] array and then use String[].Length for number of lines.

something like as below:

String[] linestext = sb.Split(newline)
Console.Writeline(linetext.Length)
swapneel
+2  A: 

Derive your own line counting StringBuilder where AppendLine ups an internal line count and provides a method to get the value of line count.

JLWarlow
+1  A: 

You can create a wrapper class do the following:

public class Wrapper
{
    private StringBuilder strBuild = null;
    private int count = 0;
    public Wrapper(){
        strBuild = new StringBuilder();
    }
    public void AppendLine(String toAppendParam){
        strBuild.AppendLine(toAppendParam);
        count++;
    }
    public StringBuilder getStringBuilder(){
        return strBuild;
    }

    public int getCount(){
        return count;
    }
}
Koekiebox
Fixed your code formatting, but you may want to change this to be more idiomatic to C# rather than Java.
sixlettervariables
+5  A: 

Sorted by efficiency:

  1. Counting your AppendLine() calls
  2. Calling IndexOf() in a loop
  3. Using Regex
  4. Using String.Split()

The last one is extraordinary expensive and generates lots of garbage, don't use.

Hans Passant
I think option #1 can lead to errors, since it doesn't guarantee that the counted AppendLine() calls will truly match the real count of newlines. The other options make eminent sense.
code4life
Meh, newlines do not fall from the sky. But yes, efficiency is risking maintainability here.
Hans Passant
@Hans, they may not fall from the sky but they can come from `Environment.NewLine`, `\r\n`, `\n`, or even from content that is passed to one of the other methods.
Matthew Whited
A: 
Binary Worrier
`b.ToString().Count(c => c =='\n')` would work here too, and might not be much less efficient (aside from creating a separate copy of the string!).
Gabe
@Gabe: I should have known `b.ToString().Count(c => c =='\n')` takes about 2/3 the time my enumerator does.
Binary Worrier
A: 

If you're going to use String.Split(), you will need to split the string with some options. Like this:

static void Main(string[] args)
{
    var sb = new StringBuilder();
    sb.AppendLine("this");
    sb.AppendLine("is");
    sb.AppendLine("test");

    // StringSplitOptions.None counts the last (blank) newline 
    // which the last AppendLine call creates
    // if you don't want this, then replace with 
    // StringSplitOptions.RemoveEmptyEntries
    var lines = sb.ToString().Split(
        new string[] { 
            System.Environment.NewLine }, 
        StringSplitOptions.None).Length;

    Console.WriteLine("Number of lines: " + lines);

    Console.WriteLine("Press enter to exit.");
    Console.ReadLine();
}

This results in:

Number of lines: 4

code4life