Export (0) Print
Expand All

BufferedStream Class

Adds a buffering layer to read and write operations on another stream. This class cannot be inherited.

Namespace:  System.IO
Assembly:  mscorlib (in mscorlib.dll)

[ComVisibleAttribute(true)]
public sealed class BufferedStream : Stream

For an example of creating a file and writing text to a file, see How to: Write Text to a File. For an example of reading text from a file, see How to: Read Text from a File. For an example of reading from and writing to a binary file, see How to: Read and Write to a Newly Created Data File.

A buffer is a block of bytes in memory used to cache data, thereby reducing the number of calls to the operating system. Buffers improve read and write performance. A buffer can be used for either reading or writing, but never both simultaneously. The Read and Write methods of BufferedStream automatically maintain the buffer.

BufferedStream can be composed around certain types of streams. It provides implementations for reading and writing bytes to an underlying data source or repository. Use BinaryReader and BinaryWriter for reading and writing other data types. BufferedStream is designed to prevent the buffer from slowing down input and output when the buffer is not needed. If you always read and write for sizes greater than the internal buffer size, then BufferedStream might not even allocate the internal buffer. BufferedStream also buffers reads and writes in a shared buffer. It is assumed that you will almost always be doing a series of reads or writes, but rarely alternate between the two of them.

The following code example shows how to use the BufferedStream class over the NetworkStream class to increase the performance of certain I/O operations. Start the server on a remote computer before starting the client. Specify the remote computer name as a command-line argument when starting the client. Vary the dataArraySize and streamBufferSize constants to view their effect on performance.

using System;
using System.IO;
using System.Globalization;
using System.Net;
using System.Net.Sockets;

public class Client
{
    const int dataArraySize    =   100;
    const int streamBufferSize =  1000;
    const int numberOfLoops    = 10000;

    static void Main(string[] args)
    {
        // Check that an argument was specified when the 
        // program was invoked. 
        if(args.Length == 0)
        {
            Console.WriteLine("Error: The name of the host computer" +
                " must be specified when the program is invoked.");
            return;
        }

        string remoteName = args[0];

        // Create the underlying socket and connect to the server.
        Socket clientSocket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

        clientSocket.Connect(new IPEndPoint(
            Dns.Resolve(remoteName).AddressList[0], 1800));

        Console.WriteLine("Client is connected.\n");

        // Create a NetworkStream that owns clientSocket and 
        // then create a BufferedStream on top of the NetworkStream. 
        // Both streams are disposed when execution exits the 
        // using statement. 
        using(Stream
            netStream = new NetworkStream(clientSocket, true),
            bufStream =
                  new BufferedStream(netStream, streamBufferSize))
        {
            // Check whether the underlying stream supports seeking.
            Console.WriteLine("NetworkStream {0} seeking.\n",
                bufStream.CanSeek ? "supports" : "does not support");

            // Send and receive data. 
            if(bufStream.CanWrite)
            {
                SendData(netStream, bufStream);
            }
            if(bufStream.CanRead)
            {
                ReceiveData(netStream, bufStream);
            }

            // When bufStream is closed, netStream is in turn 
            // closed, which in turn shuts down the connection 
            // and closes clientSocket.
            Console.WriteLine("\nShutting down the connection.");
            bufStream.Close();
        }
    }

    static void SendData(Stream netStream, Stream bufStream)
    {
        DateTime startTime;
        double networkTime, bufferedTime;

        // Create random data to send to the server.
        byte[] dataToSend = new byte[dataArraySize];
        new Random().NextBytes(dataToSend);

        // Send the data using the NetworkStream.
        Console.WriteLine("Sending data using NetworkStream.");
        startTime = DateTime.Now;
        for(int i = 0; i < numberOfLoops; i++)
        {
            netStream.Write(dataToSend, 0, dataToSend.Length);
        }
        networkTime = (DateTime.Now - startTime).TotalSeconds;
        Console.WriteLine("{0} bytes sent in {1} seconds.\n",
            numberOfLoops * dataToSend.Length,
            networkTime.ToString("F1"));

        // Send the data using the BufferedStream.
        Console.WriteLine("Sending data using BufferedStream.");
        startTime = DateTime.Now;
        for(int i = 0; i < numberOfLoops; i++)
        {
            bufStream.Write(dataToSend, 0, dataToSend.Length);
        }
        bufStream.Flush();
        bufferedTime = (DateTime.Now - startTime).TotalSeconds;
        Console.WriteLine("{0} bytes sent in {1} seconds.\n",
            numberOfLoops * dataToSend.Length,
            bufferedTime.ToString("F1"));

        // Print the ratio of write times.
        Console.WriteLine("Sending data using the buffered " +
            "network stream was {0} {1} than using the network " +
            "stream alone.\n",
            (networkTime/bufferedTime).ToString("P0"),
            bufferedTime < networkTime ? "faster" : "slower");
    }

    static void ReceiveData(Stream netStream, Stream bufStream)
    {
        DateTime startTime;
        double networkTime, bufferedTime = 0;
        int bytesReceived = 0;
        byte[] receivedData = new byte[dataArraySize];

        // Receive data using the NetworkStream.
        Console.WriteLine("Receiving data using NetworkStream.");
        startTime = DateTime.Now;
        while(bytesReceived < numberOfLoops * receivedData.Length)
        {
            bytesReceived += netStream.Read(
                receivedData, 0, receivedData.Length);
        }
        networkTime = (DateTime.Now - startTime).TotalSeconds;
        Console.WriteLine("{0} bytes received in {1} seconds.\n",
            bytesReceived.ToString(),
            networkTime.ToString("F1"));

        // Receive data using the BufferedStream.
        Console.WriteLine("Receiving data using BufferedStream.");
        bytesReceived = 0;
        startTime = DateTime.Now;

        int numBytesToRead = receivedData.Length;

        while (numBytesToRead > 0)
        {
            // Read may return anything from 0 to numBytesToRead. 
            int n = bufStream.Read(receivedData,0, receivedData.Length);
            // The end of the file is reached. 
            if (n == 0)
                break;
            bytesReceived += n;
            numBytesToRead -= n;
        }

        bufferedTime = (DateTime.Now - startTime).TotalSeconds;
        Console.WriteLine("{0} bytes received in {1} seconds.\n",
            bytesReceived.ToString(),
            bufferedTime.ToString("F1"));

        // Print the ratio of read times.
        Console.WriteLine("Receiving data using the buffered network" +
            " stream was {0} {1} than using the network stream alone.",
            (networkTime/bufferedTime).ToString("P0"),
            bufferedTime < networkTime ? "faster" : "slower");
    }
}
using System;
using System.Net;
using System.Net.Sockets;

public class Server 
{
    static void Main() 
    {
        // This is a Windows Sockets 2 error code. 
        const int WSAETIMEDOUT = 10060;

        Socket serverSocket;
        int bytesReceived, totalReceived = 0;
        byte[] receivedData = new byte[2000000];

        // Create random data to send to the client.
        byte[] dataToSend = new byte[2000000];
        new Random().NextBytes(dataToSend);

        IPAddress ipAddress =
            Dns.Resolve(Dns.GetHostName()).AddressList[0];

        IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, 1800);

        // Create a socket and listen for incoming connections. 
        using(Socket listenSocket = new Socket(
            AddressFamily.InterNetwork, SocketType.Stream, 
            ProtocolType.Tcp))
        {
            listenSocket.Bind(ipEndpoint);
            listenSocket.Listen(1);

            // Accept a connection and create a socket to handle it.
            serverSocket = listenSocket.Accept();
            Console.WriteLine("Server is connected.\n");
        }

        try
        {
            // Send data to the client.
            Console.Write("Sending data ... ");
            int bytesSent = serverSocket.Send(
                dataToSend, 0, dataToSend.Length, SocketFlags.None);
            Console.WriteLine("{0} bytes sent.\n", 
                bytesSent.ToString());

            // Set the timeout for receiving data to 2 seconds.
            serverSocket.SetSocketOption(SocketOptionLevel.Socket,
                SocketOptionName.ReceiveTimeout, 2000);

            // Receive data from the client.
            Console.Write("Receiving data ... ");
            try
            {
                do
                {
                    bytesReceived = serverSocket.Receive(receivedData,
                        0, receivedData.Length, SocketFlags.None);
                    totalReceived += bytesReceived;
                }
                while(bytesReceived != 0);
            }
            catch(SocketException e)
            {
                if(e.ErrorCode == WSAETIMEDOUT)
                {
                    // Data was not received within the given time. 
                    // Assume that the transmission has ended.
                }
                else
                {
                    Console.WriteLine("{0}: {1}\n", 
                        e.GetType().Name, e.Message);
                }
            }
            finally
            {
                Console.WriteLine("{0} bytes received.\n",
                    totalReceived.ToString());
            }
        }
        finally
        {
            serverSocket.Shutdown(SocketShutdown.Both);
            Console.WriteLine("Connection shut down.");
            serverSocket.Close();
        }
    }
}

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0, 2.0, 1.1, 1.0

Community Additions

ADD
Show:
© 2014 Microsoft