【问题标题】:How to stream data to FTP如何将数据流式传输到 FTP
【发布时间】:2015-02-07 16:08:17
【问题描述】:

我遇到了OutOfMemoryException。我的流程如下:

  1. 我从数据库中读取数据(大集合,数百万行)。
  2. 我遍历检索到的数据并将其附加到StringBuilder
  3. 我在 StringBuilder 上调用 ToString 并使用 SFTP (Renci.SSHnet) 将字符串上传到新文件。

此流程不起作用,因为要保存在内存中的文件太多。我决定做一些改变:

  • 现在使用数据读取器获取数据并返回(而不是返回整个数据集)
  • 我无法在StringBuilder 上调用ToString,因为字符串太大而无法放入内存。我将StringBuilder 更改为StreamWriter,这样我就可以直接写入一个流,然后SFTP 上传过程可以使用该流。

这就是事情开始变得棘手的地方。我想在我的数据处理代码中将新数据附加到StreamWriter,而 SFTP 上传代码从同一流中读取,对其进行 GZIP 压缩并上传数据。请注意,它应该只在远程服务器上创建一个文件。换句话说:我想在上传处理过的数据的同时处理数据,这样我就可以保持非常低的内存占用。我无法让这个工作。这是我想出的(简化示例),但它从不读取数据:

static void Main()
{
    using (var stream = new MemoryStream())
    {
        WriteToStream(stream, GetData());
        ReadFromStream(stream);
    }
}

static IEnumerable<string> GetData()
{
    for (int i = 0; i < 10; i++)
    {
        var date = DateTime.Now;
        Console.WriteLine("{0:O} - Fetched some data: {1}", date, i);
        yield return string.Format("{0}", i);
    }
}

static void WriteToStream(Stream stream, IEnumerable<string> data)
{
    using (var writer = new StreamWriter(stream))
    {
        foreach (string str in data)
        {
            Console.WriteLine("{0:O} - Wrote some data: {1}", DateTime.Now, str);
            writer.WriteLine("{0}", str);
        }
    }
}

static void ReadFromStream(Stream stream)
{
    using (var reader = new StreamReader(stream))
    {
        while (reader.Peek() >= 0)
        {
            var res = reader.ReadLine();
            Console.WriteLine("{0} - Read some data: {1}", DateTime.Now, res);
        }
    }
}

谁能指出我正确的方向?

【问题讨论】:

  • 参见stackoverflow.com/questions/24253975/…,这与您尝试做的非常相似。
  • 您的示例不起作用,因为StreamWriter 关闭时StreamWriter 关闭了基础流(MemoryStream)。您可以使用this overloaded constructor 来防止这种情况。在调用ReadFromStream 之前,您还需要将MemoryStream 位置设置为0。但这仍然无法满足您的需求,因为 FTP 上传组件可能不会配合。我上面提供的链接可以让你做你想做的事。但是,您需要将生产者或消费者放在单独的线程上。

标签: c# memory ftp stream streaming


【解决方案1】:

与其自己创建一个新流并将该流传递给 ftp 组件,不如使用 ftp 组件的方法来启动一个新流 (SftpClient.Open(...)) 并写入该流。类似于您的 WriteToStream 方法,只是可能需要将 writeline 替换为 write。

你的问题的其余部分仍然很有趣:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    相关资源
    最近更新 更多