使用StreamWriter写入文件比通过慢速网络的文件复制慢得多

时间:2013-01-29 16:28:59

标签: c# performance networking streamwriter

我有一个程序试图将大量文​​本写入海外远程服务器上的文件,该文件的网络连接速度很慢。

使用以下代码,其中outputFileContentStringBuilder

using (var outfile = new StreamWriter(myRemoteFilePath))
{
    outfile.Write(outputFileContent.ToString());
}

运行需要很长时间(几分钟),而如果我首先写入本地文件然后将其复制到远程位置,则会更快(20-30秒):

string tempFilePath = Path.GetTempFileName();
using (var outfile = new StreamWriter(tempFilePath))
{
    outfile.Write(outputFileContent.ToString());
}

System.IO.File.Copy(tempFilePath, myRemoteFilePath, true)

知道为什么会这样吗?我唯一的猜测是它与网络缓冲有关,或者可能是因为流编写者不知道它需要提前多大。

3 个答案:

答案 0 :(得分:9)

如果使用默认缓冲区大小创建StreamWriter,则底层SMB协议将以不大于4096字节的块发出写请求,这意味着通过网络进行大量往返。您可以将StreamWriter的缓冲区大小增加到最大64k,以减少往返次数:

using (var outfile = new StreamWriter(myRemoteFilePath, false, Encoding.ASCII, 0x10000))

将缓冲区大小增加到64k以上在任何情况下都无济于事,因为底层SMB协议不支持超过64k的缓冲区长度。请注意,直接文件复制仍然使用SMB协议,因此从网络流量角度来看,除了缓冲区大小之外,操作之间几乎没有差别。

答案 1 :(得分:-1)

这不是魅力......但它确实有效。我解决了它使用StringBuilder从数据库表中将1.000.000行写入带有个人缓冲区的CSV(dr是来自数据库的数据引导器)。这个解决方案要快得多:

            using (StreamWriter sw = new StreamWriter(filePath))
            {
                StringBuilder sb = new StringBuilder();
                int lines = 0;
                while (dr.Read())
                {
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        sb.Append(dr[i].ToString() + ';');
                    }
                    sb.AppendLine();

                    if (lines % 10000 == 0)
                    {
                        sw.Write(sb.ToString());
                        sb = new StringBuilder();
                    }
                    lines++;
                }

                dr.Close();

答案 2 :(得分:-2)

我不是安全专家,但在我看来,这与许可问题最为相关。

每当您在远程服务器上的磁盘上写入某些内容时,将会针对执行该操作的用户检查权限。自然写作的许可。

如果不是副本,则仅执行该控制。所以它很多更快。

事实上,为了证明这一点,您可以尝试通过网络复制多个文件,并在通过网络复制ZIP文件(压缩状态下具有相同数量的内存)之后。在第二种情况下,对于单个ZIP文件,它将更快,因为权限控制仅执行一次。

希望这有帮助。