如何使用 conduit 获取惰性 ByteString 并将其写入文件(在常量内存中)
How to take a lazy ByteString and write it to a file (in constant memory) using conduit
我正在使用 amazonka 流式传输 S3 文件的下载,我使用 sinkBody
函数继续流式传输。目前我下载的文件如下:
getFile bucketName fileName = do
resp <- send (getObject (BucketName bucketName) fileName)
sinkBody (resp ^. gorsBody) sinkLazy
其中 sinkBody :: MonadIO m => RsBody -> ConduitM ByteString Void (ResourceT IO) a -> m a
。为了在常量内存中 运行,我认为 sinkLazy
是从管道流中获取值的一个很好的选择。
在此之后,我想将惰性字节串数据(S3 文件)保存到本地文件中,为此我使用以下代码:
-- fetch stream of data from S3
bytestream <- liftIO $ AWS.runResourceT $ runAwsT awsEnv $ getFile serviceBucket key
-- create a file
liftIO $ writeFile filePath ""
-- write content of stream into the file (strict version), keeps data in memory...
liftIO $ runConduitRes $ yield bytestream .| mapC B.toStrict .| sinkFile filePath
但是这段代码有一个缺陷,我需要在内存中“实现”所有的惰性字节串,这意味着它不能运行 in constant space.
有什么方法可以使用 conduit 来 yield
惰性字节串并将其保存到常量内存中的文件中?
或者,任何其他不使用 sinkLazy
并解决保存到文件 运行ning 常量 space 中的问题的方法?
编辑
我也测试了将惰性字节流直接写到文件中,如下,但是这样消耗的内存大约是文件大小的2倍。 (writeFile
来自 Data.ByteString.Lazy
)。
bytestream <- liftIO $ AWS.runResourceT $ runAwsT awsEnv $ getFile serviceBucket key
writeFile filename bytestream
嗯,像 conduit
这样的流式库的目的是实现惰性数据结构和操作的一些好处(惰性 ByteString
s、惰性 I/O 等。 ) 同时更好地控制内存使用。 sinkLazy
函数的目的是将数据从 conduit
生态系统中取出,其内存占用控制良好,并返回到具有相关 space 泄漏的惰性对象的狂野西部。所以,这就是你的问题。
与其将流从 conduit
中导出并放入惰性 ByteString
,您可能希望将数据保留在 conduit
中并将流直接导入文件中,使用类似于 sinkFile
。我没有启动 AWS 测试程序 运行,但以下类型检查并可能会执行您想要的操作:
import Conduit
import Control.Lens
import Network.AWS
import Network.AWS.S3
getFile bucketName fileName outputFileName = do
resp <- send (getObject (BucketName bucketName) fileName)
sinkBody (resp ^. gorsBody) (sinkFile outputFileName)
我正在使用 amazonka 流式传输 S3 文件的下载,我使用 sinkBody
函数继续流式传输。目前我下载的文件如下:
getFile bucketName fileName = do
resp <- send (getObject (BucketName bucketName) fileName)
sinkBody (resp ^. gorsBody) sinkLazy
其中 sinkBody :: MonadIO m => RsBody -> ConduitM ByteString Void (ResourceT IO) a -> m a
。为了在常量内存中 运行,我认为 sinkLazy
是从管道流中获取值的一个很好的选择。
在此之后,我想将惰性字节串数据(S3 文件)保存到本地文件中,为此我使用以下代码:
-- fetch stream of data from S3
bytestream <- liftIO $ AWS.runResourceT $ runAwsT awsEnv $ getFile serviceBucket key
-- create a file
liftIO $ writeFile filePath ""
-- write content of stream into the file (strict version), keeps data in memory...
liftIO $ runConduitRes $ yield bytestream .| mapC B.toStrict .| sinkFile filePath
但是这段代码有一个缺陷,我需要在内存中“实现”所有的惰性字节串,这意味着它不能运行 in constant space.
有什么方法可以使用 conduit 来
yield
惰性字节串并将其保存到常量内存中的文件中?或者,任何其他不使用
sinkLazy
并解决保存到文件 运行ning 常量 space 中的问题的方法?
编辑
我也测试了将惰性字节流直接写到文件中,如下,但是这样消耗的内存大约是文件大小的2倍。 (writeFile
来自 Data.ByteString.Lazy
)。
bytestream <- liftIO $ AWS.runResourceT $ runAwsT awsEnv $ getFile serviceBucket key
writeFile filename bytestream
嗯,像 conduit
这样的流式库的目的是实现惰性数据结构和操作的一些好处(惰性 ByteString
s、惰性 I/O 等。 ) 同时更好地控制内存使用。 sinkLazy
函数的目的是将数据从 conduit
生态系统中取出,其内存占用控制良好,并返回到具有相关 space 泄漏的惰性对象的狂野西部。所以,这就是你的问题。
与其将流从 conduit
中导出并放入惰性 ByteString
,您可能希望将数据保留在 conduit
中并将流直接导入文件中,使用类似于 sinkFile
。我没有启动 AWS 测试程序 运行,但以下类型检查并可能会执行您想要的操作:
import Conduit
import Control.Lens
import Network.AWS
import Network.AWS.S3
getFile bucketName fileName outputFileName = do
resp <- send (getObject (BucketName bucketName) fileName)
sinkBody (resp ^. gorsBody) (sinkFile outputFileName)