加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何动态生成大数据流

发布时间:2020-12-16 18:38:49 所属栏目:安全 来源:网络整理
导读:我必须动态生成一个大文件.读取数据库并将其发送给客户端. 我读了一些文档,我做了这个 val streamContent: Enumerator[Array[Byte]] = Enumerator.outputStream { os = // new PrintWriter() read from database and for each record // do some logic and w
我必须动态生成一个大文件.读取数据库并将其发送给客户端.
我读了一些文档,我做了这个

val streamContent: Enumerator[Array[Byte]] = Enumerator.outputStream {
        os => 
              // new PrintWriter() read from database and for each record 
              // do some logic and write
              // to outputstream
      }
      Ok.stream(streamContent.andThen(Enumerator.eof)).withHeaders(
              CONTENT_DISPOSITION -> s"attachment; filename=someName.csv"
        )

我一般只在一周内对scala很新,所以不要指导我的声誉.

我的问题是:

1)这是最好的方法吗?我发现这个,如果我有一个大文件,这将加载到内存中,也不知道在这种情况下什么是块大小,如果它将为每个write()发送不方便.

2)我发现这个方法Enumerator.fromStream(data:InputStream,chunkedSize:int)更好一点,因为它有一个块大小,但我没有inputStream导致我即时创建文件.

解决方法

docs for Enumerator.outputStream中有一个注释:

Not [sic!] that calls to write will not block,so if the iteratee that is being fed to is slow to consume the input,the OutputStream will not push back. This means it should not be used with large streams since there is a risk of running out of memory.

如果发生这种情况取决于您的情况.如果你可以并且将在几秒钟内产生千兆字节,你应该尝试不同的东西.我不确定是什么,但我从Enumerator.generateM()开始.但是对于很多情况来说,你的方法非常好.看看at this example by Ga?tan Renaudeau for serving a Zip file that’s generated on the fly in the same way you’re using it:

val enumerator = Enumerator.outputStream { os =>
  val zip = new ZipOutputStream(os);
  Range(0,100).map { i =>
    zip.putNextEntry(new ZipEntry("test-zip/README-"+i+".txt"))
    zip.write("Here are 100000 random numbers:n".map(_.toByte).toArray)
    // Let's do 100 writes of 1'000 numbers
    Range(0,100).map { j =>
      zip.write((Range(0,1000).map(_=>r.nextLong).map(_.toString).mkString("n")).map(_.toByte).toArray);
    }
    zip.closeEntry()
  }
  zip.close()
}
Ok.stream(enumerator >>> Enumerator.eof).withHeaders(
  "Content-Type"->"application/zip","Content-Disposition"->"attachment; filename=test.zip"
)

请记住,如果您想要升级,Ok.stream已被更新版本的Play中的Ok.chunked取代.

至于块大小,你总是可以使用Enumeratee.grouped来收集一堆值并将它们作为一个块发送.

val grouper = Enumeratee.grouped(  
  Traversable.take[Array[Double]](100) &>> Iteratee.consume()  
)

然后你会做类似的事情

Ok.stream(enumerator &> grouper >>> Enumerator.eof)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读