2015-06-25 6 views
0

В C++ можно писать буферизованный ввод-вывод с помощью setvbuf. как добиться того же результата в C#. Есть ли метод, доступный для записи буферизации ввода/вывода в C#Как записать данные в буфер перед записью на диск в C#

+5

BufferedStream класс: https://msdn.microsoft.com/en-us/library/system.io.bufferedstream(v=vs.110).aspx – Marco

+0

@Serv Я предлагаю вам сделать ответ. – Richard

+0

Обратите внимание, что для записи текста [StreamWriter] (https://msdn.microsoft.com/library/72d9f8d5.aspx) имеет конструктор, который задает размер буфера (и по умолчанию использует буфер с 1024 байтами) – xanatos

ответ

0

Как уже отметил есть BufferedStream класса

добавляет буферный слой, чтобы операции чтения и запись на другой поток. Этот класс не может быть унаследован.

Пример кода из MSDN:

стороне сервера:

// 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(); 
    } 
} 

стороне клиента:

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"); 
    } 
} 
+0

преподобный, то есть серверная сторона. Пропущена клиентская сторона. Исправит это как можно скорее – Marco

0

Оба FileStream и StreamWriter внутренне буферизацией (они имеют размер буфера по умолчанию из 4096 и 1024 байта и конструкторы, способные его модифицировать).

Сложный вопрос заключается в том, как писать в файл без использования буфера :-) И обратите внимание, что благодаря тому, как они работают, StreamWriter, который записывает в файл, будет иметь двойной буфер (буфер StreamWriter независимо от FileStream). По меньшей мере StreamWriter имеет свойство AutoFlush, которое, если установлено в true, будет заподлицо после каждой записи.