I'm writing an app to let me interact and debug my android over USB using the android SDK and the ADB command. I create a Process with redirected input and output streams and basically run "ADB shell", and I want to be able to wait for the prompt, enter commands and parse the results. Here's a sample running `ps` and getting the results: CreateProcess("shell"); string data = await ReadToPrompt(":/ $ "); _Process.StandardInput.WriteLine("ps"); string echo = await ReadLine(); // my command echoed back string dataAndPrompt = await ReadToPrompt(":/ $ "); It works (although I'm getting extra CR in the byte stream, CR/LF is coming as CR/CF/LF), but I can't help but wonder if there's a better way than what I have: Process _Process; MemoryStream _Remaining; // bytes left after ReadToPrompt byte[] _Buffer = new byte[0x10000]; public async Task<string> ReadLine() { return await ReadToPrompt("\r\n"); } public async Task<string> ReadToPrompt(string prompt) { MemoryStream ms = _Remaining == null ? new MemoryStream() : _Remaining; int promptSize = prompt.Length; int pos = 0; while (true) { // read what we can from the process's standard output int count = await _Process.StandardOutput.BaseStream.ReadAsync(_Buffer, 0, _Buffer.Length); ms.Write(_Buffer, 0, count); // write new data to memory stream // convert all new bytes to check for prompt string testString = Encoding.ASCII.GetString(ms.GetBuffer(), pos, (int)(ms.Position - pos)); int promptPos = testString.IndexOf(prompt); if (promptPos > 0) { // we found it, result is up to and including prompt int stripLength = pos + promptPos + promptSize; string result = Encoding.ASCII.GetString(ms.GetBuffer(), 0, stripLength); // store remaining data in a MemoryStream for the next call _Remaining = new MemoryStream(); _Remaining.Write(ms.GetBuffer(), stripLength, (int)(ms.Position - stripLength)); return result.Replace("\r\r", "\r"); } // we didn't find it but we know it isn't in what we got, so move first position // to check to the position - promptSize pos = (int)(ms.Position - promptSize); pos = (pos < 0) ? 0 : pos; } } Is there something I can reliably do to keep from creating new `MemoryStream`s? For instance, could I do an array copy on `MemoryStream.GetBuffer()` to itself and use `MemoryStream.SetLength()`? Is there an entirely better way to do it than using async and await?