【问题标题】:IEnumerable emit as stream?IEnumerable 作为流发射?
【发布时间】:2018-08-02 18:20:25
【问题描述】:

有没有办法获取IEnumerable<T> 并将其作为类似这样的可读流发出?

private void DoTheThing(IEnumerable<Foo> foos)
{
    using (var myStream = foos.EmitAsStream(f =>
    {
        var line = JsonConvert.SerializeObject(f);
        return line;
    }))
    using(var streamReader = new StreamReader(myStream))
    {
        while (!streamReader.EndOfStream)
        {
            var line = streamReader.ReadLine();
            Console.WriteLine(line);
        }
    }
}

显然,这存在一些问题,例如,它似乎暗示 StreamWriter 没有指定,但想法是流读取器只会通过 IEnumerable 在引擎盖下产生枚举,应用转换委托,并拉取结果,而无需在内存中创建任何新的、可能很大的对象。

我在内存中有一些非常大的可枚举对象,我需要将它们推送到接受流的外部位置(如 Amazon S3)。我真的负担不起用集合构建 MemoryStream 并发送它;我可以假脱机到磁盘并从磁盘读取,但如果可以选择,我不希望这样做,因为这似乎是一个额外的步骤。

这可能吗?如果可以的话,实用吗?

【问题讨论】:

    标签: c# stream ienumerable


    【解决方案1】:

    如果我正确理解您的问题,您可以使用TakeWhile 来实现。

    类似:

    while(..end ..) 
    {
       var enumeration = foos.TakeWhile(..line bounds..);
       var stream = StreamFromEnum(enumeration ); //custom implementation
       // stream --> S3
    }
    

    我假设您对“线”有一些自定义定义,这可能是流中数据的某种步幅/切片。

    A lazily-evaluated stream wrapper for IEnumerableIEnumerable&lt;T&gt; -> Stream 转换的一种可能实现。

    【讨论】:

    • 这似乎没有发出流。我需要最终发送一个流。
    • 您可以将“切片”转换为字节流 - 我猜,字节是 S3 所需要的。
    • 所以重点是在流假脱机时通过IEnumerable 有点“按需”产生枚举,而不会占用大量内存。 S3 客户端只接受一个流;我不想要每一行都有一个流,我只想逐行处理流输入
    • @JeremyHolovacs:但最终将发送到 S3 的流转换并不便宜。据我了解,IEnumerable&lt;T&gt; 您处理的数据很多 - 因此我建议逐个处理它。如果一次全部转换,发送到 S3 是可行的方案,你也可以这样尝试。
    • 我认为EnumerableStream 正是我想要的。
    【解决方案2】:

    EnumerableToStream 包将完全按照您的要求进行:

    using EnumerableToStream;
    
    using (var myStream = foos.Select(f =>
    {
        var line = JsonConvert.SerializeObject(f);
        return line;
    }).ToStream())
    

    ToStream() 方法是最神奇的方法。如果您对实现细节感兴趣,请查看source code

    【讨论】:

      猜你喜欢
      • 2022-01-20
      • 2016-05-13
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      相关资源
      最近更新 更多