5

How can I get the length of a StreamReader, as I know nothing will be written to it anymore. I thought that maybe I could pass all the data to a MemoryStream, which has a method called Length, but I got stuck on how to append a byte[] to a MemoryStream.

private void Cmd(string command, string parameter, object stream)
        {

            StreamWriter writer = (StreamWriter)stream;
            StreamWriter input;
            StreamReader output;

            Process process = new Process();

            try
            {
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.FileName = "cmd";
                process.Start();

                input = process.StandardInput;
                output = process.StandardOutput;
                input.WriteLine(command + " " + parameter);
                input.WriteLine("exit");

                using (MemoryStream ms = new MemoryStream())
                {
                    int length = 1024;
                    char[] charbuffer = new char[length];
                    byte[] bytebuffer = new byte[length];

                    while (!output.EndOfStream)
                    {
                        output.Read(charbuffer, 0, charbuffer.Length);
                        for (int i = 0; i < length; i++)
                        {
                            bytebuffer[i] = Convert.ToByte(charbuffer[i]);
                        }
                        //append bytebuffer to memory stream here
                    }

                    long size = ms.Length;

                    writer.WriteLine(size);
                    writer.Flush(); //send size of the following message

                    //send message
                }

            }
            catch (Exception e)
            {
                InsertLog(2, "Could not run CMD command");
                writer.WriteLine("Not valid. Ex: " + e.Message);
            }
            writer.Flush();
        }

So, how can I dinamically append a byte[] to a MemoryStream? There is any way better than this to get the length of output so I can warn the other end about the size of the message which will be sent?

Bruno Klein
  • 3,217
  • 5
  • 29
  • 39
  • What do you mean by `size`or by `length`? – Benjamin Toueg Feb 01 '13 at 00:12
  • When referring to both of them I meant the quantity of bytes/chars on the respective variable. – Bruno Klein Feb 01 '13 at 00:14
  • 1
    I don't understand.. you have the length of the `bytebuffer`.. why not just use that? – Simon Whitehead Feb 01 '13 at 00:16
  • Your code confuses me a lot. Why would you call your `StreamWriter` `input`and `StreamReader` `output`? – Benjamin Toueg Feb 01 '13 at 00:17
  • @Simon Whitehead: Because it's just a buffer, the message will be WAY larger than 1024. The idea of this code is basically as follows: I will read `output` step-by-step (each step is 1024 chars), then, on each step I will convert the chars just read to bytes (`MemoryStream`) and append the 1024 bytes to the memory stream. At the end I will have a `MemoryStream` with all my message. Then I can use it to send the message and use the method `Length` to warn the other end about the length/size of the message. – Bruno Klein Feb 01 '13 at 00:20
  • @btoueg: Because Streamwriter represents the input of Command Prompt and Reader the output. – Bruno Klein Feb 01 '13 at 00:22
  • 3
    @BrunoKlein But you're looping over the stream until `EOF`.. and storing everything in `bytebuffer`. – Simon Whitehead Feb 01 '13 at 00:23
  • 1
    @BrunoKlein one more remark, appending to my answer, you could use `m.WriteByte` method to write each byte into the `MemoryStream` at once. This would let you eliminate the `bytebuffer` at all. – horgh Feb 01 '13 at 00:54

3 Answers3

6

Does this work for you?

        StreamReader sr = new StreamReader(FilePath);
        long x = sr.BaseStream.Length;
Steve Sims
  • 111
  • 2
  • 3
4

Stream has a Length property, but will throw an exception if the stream doesn't support seek operations. A network stream for example will throw an exception if you try to read .Length. In your code, you're processing an input stream of a process. Consider if that were user input - how would you know the length until you were completely finished reading?

If you're reading a file, you can get the length with stream.Length.

In .NET 4+, you can copy one stream to another with Stream.CopyTo, eg:

inputStream.CopyTo(outputStream);

You can also load the bytes into memory with:

byte[] data;
using (var ms = new MemoryStream())
{
    stream.CopyTo(ms);
    data = ms.ToArray();
}
drch
  • 3,040
  • 1
  • 18
  • 29
  • Can you provide an example? Because I can't use `CopyTo` in order to copy `output` to `ms`. – Bruno Klein Feb 01 '13 at 00:28
  • @BrunoKlein both parameters are streams, eg stream.CopyTo(someOtherStream). Your `output` variable is a StreamReader. See: https://gist.github.com/25eb147ef11305171b20 – drch Feb 01 '13 at 00:36
  • 1
    Apparently `StreamReader` does not have a method called `CopyTo`. – Bruno Klein Feb 01 '13 at 00:39
1

MemoryStream has MemoryStream.Write Method , which writes a byte array to the stream:

ms.Write(bytebuffer,0,bytebuffer.Length);

So, you can call it to add another portion of bytes to the output stream. However remember, to be able to read from MemoryStream after all write operations are over, you'll have to use MemoryStream.Seek Method to set the position within the current stream to its beginning:

//all write operations
ms.Seek(0, SeekOrigin.Begin);
//now ready to be read

This is the easiest approach. Of cousre, you may dynamically move across the stream, while reading/writing. But that may be error prone.

To get the length of the stream, i.e. ms.Length, you don't have to seek the begining of the stream.

I guess, it's worth to note, that if bytebuffer is used only to store bytes before copying them into the MemoryStream, you could use MemoryStream.WriteByte Method instead. This would let you abolish bytebuffer at all.

for (int i = 0; i < length; i++)
{
    ms.WriteByte(Convert.ToByte(charbuffer[i]));
}
horgh
  • 17,918
  • 22
  • 68
  • 123