【问题标题】:How can I write to a file instead of an in memory byte array?如何写入文件而不是内存字节数组?
【发布时间】:2015-10-09 00:42:37
【问题描述】:

目前我有这段代码,它通过网络接收信息,将其存储到内存字节数组中,然后通过 FileStream 将其写出。

 StreamReader reader = new StreamReader(tcpClient.GetStream());

  // first message is file size
         string cmdFileSize = reader.ReadLine();

  // first message is filename
        string cmdFileName = reader.ReadLine();

        int length = Convert.ToInt32(cmdFileSize);
        byte[] buffer = new byte[length];
        int received = 0;
        int read = 0;
        int size = 1024;
        int remaining = 0;


   while (received < length)
        {
            remaining = length - received;
            if (remaining < size)
            {
                size = remaining;
            }

            read = tcpClient.GetStream().Read(buffer, received, size);
            received += read;
            if (read < size)
            {
                break;
            }
        }    

在此之后,“缓冲区”通过 FileStream 写入文件。这很好用,但是当我有很大的文件时,显然会占用大量内存。我想将这些文件直接流式传输到磁盘,而不是写入内存然后将它们重写到硬盘驱动器。

我该怎么做?

【问题讨论】:

  • 如果你想写入文件而不是hostprojects.net/snippets/cs/76/…
  • @MethodMan 是的,你可以使用 StreamReader 来做到这一点,但我认为底层代码最终可能会使用缓冲区。
  • 您可以尝试这样的操作,以确保对于较大的文件,您可以将1024 的大小乘以这样的byte[] buffer = new byte[16 * 1024];
  • 例如,我使用了一种在从 ResponseStream 读取时执行类似操作的方法。您想查看我正在使用的方法吗?您只需要稍微改变它以适用于您的用例..

标签: c# .net sockets file-transfer


【解决方案1】:

您不能只使用 StreamWriter 将内容流式传输到文件中吗?

StreamReader reader = new StreamReader(tcpClient.GetStream());

// first message is file size
string cmdFileSize = reader.ReadLine();

// first message is filename
string cmdFileName = reader.ReadLine();

int length = Convert.ToInt32(cmdFileSize);
byte[] buffer = new byte[length];
int received = 0;
int read = 0;
int size = 1024;
int remaining = 0;

using (FileStream writer = File.OpenWrite("outfile.dat"))
{
    while (received < length)
    {
        remaining = length - received;
        if (remaining < size)
        {
            size = remaining;
        }

        read = tcpClient.GetStream().Read(buffer, 0, size);
        received += read;
        writer.Write(buffer, 0, size);

        if (read < size)
        {
            break;
        }
    }
}

另外,我认为您的代码中存在错误。我假设您使用的是System.Net.Sockets.TcpClient,它在您调用GetStream() 时返回一个NetworkStream 对象。在这种情况下,Read 方法的第二个参数可能应该始终为 0。该参数指示在 buffer 变量中的哪个位置开始写入从网络读取的数据。如果不使用 0,则可能会导致数组越界异常。查看docs 中的Stream.Read 方法。

【讨论】:

  • 这可能超出了我的理解范围(意思是,这开始让我的大脑冒烟)但是你是说 getstream 的偏移量应该总是为零,因为我总是想要一切来自getstream?这对我来说很有意义。还是我弄错了?
  • 基本上我只是说应该读 = tcpClient.GetStream().Read(buffer, 0, size);
  • 我可以为新的 StreamWriter(destinationfile) 切换 File.CreateText 吗?我不会一直写文本 :) 我可能大部分时间都在写二进制文件。
  • 您可以使用FileStream,它的工作原理与NetworkStream相同。我更新了答案以反映这一点(并修复了我提到的错误)。
  • 谢谢。在实践中,这段代码运行得很慢……在环回时,它每分钟传输大约一兆字节。我不太清楚:(
猜你喜欢
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 2014-04-10
相关资源
最近更新 更多