Search code examples
c#streamwritermemorystream

c#: Getting line count from MemoryStream/StreamWriter


I use the following code to write log file:

Encoding enc = Encoding.GetEncoding(932);
MemoryStream msLog = new MemoryStream();
StreamWriter swLog = new StreamWriter(msLog, enc);
swLog.WriteLine("Line Number,Error,Additional Information"); //log header

After some complex processing I'd like to know whether there any log line was added except the header. Obviously, one way is to set some boolean variable to true whenever I use swLog.WriteLine(), but because of long and complex code I'd like to avoid this approach. How can I easily check line count of memory stream?


Solution

  • As you noted, there are other better ways to do this. However, here is a direct answer to your question:

    First, make sure that the StreamWriter has flushed the data into the stream like this:

    swLog.Flush();
    

    Then, you can use the following method to detect if the MemoryStream has more than one line:

    private bool HasMoreThanNumberOfLines(Stream stream, Encoding enc, int number_of_lines)
    {
        long current_position = stream.Position;
    
        stream.Position = 0;
    
        try
        {
            using(StreamReader sr = new StreamReader(stream, enc, true, 1024, true))
            { 
                for (int i = 0; i < number_of_lines + 1 ; i++)
                {
                    string line = sr.ReadLine();
    
                    if (line == null)
                        return false;
                }
            }
            return true;
        }
        finally
        {
            stream.Position = current_position;
        }
    }
    

    Please note that I am using a special constructor of StreamReader to make sure that it does not close the underlying stream (stream) when it is disposed of.

    Notice also how this method saves the current position of the stream, and then restores it after executing its logic so that the StreamWriter would continue to work normally.

    You can use this method like this:

    var has_another_line = HasMoreThanNumberOfLines(msLog, enc, 1);
    

    Please note that this is not thread-safe. I am assuming that the stream will be accessed by a single thread at any point in time. You would need to put some locks to make it thread-safe.