繁体   English   中英

当长度已知时,从Lazy ByteString构造RequestBodyStream

[英]Constructing RequestBodyStream from Lazy ByteString when length is known

我正在尝试修改此AWS S3上传代码以处理长度已知的Lazy ByteString (这样就不会强制在内存中完整读取它-它是通过​​网络预先发送长度的)。 看来我必须在Lazy ByteString上定义GivesPopper函数,以将其转换为RequestBodyStream 由于定义了GivesPopper的复杂方式,因此我不确定如何为Lazy ByteString编写它。 将不胜感激如何编写它的指针。 这里是它是如何从文件中读取写入:

let file ="test"
-- streams large file content, without buffering more than 10k in memory
let streamer sink = withFile file ReadMode $ \h -> sink $ S.hGet h 10240

如果我正确理解,上面代码中的streamer GivesPopper ()类型为GivesPopper () 给定一个长度为lenLazy ByteString ,在上面编写GivesPopper函数的一种好方法是什么? 我们一次可以读取一个块。

这是您要找的东西吗?

import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import System.IO

file = "test"
-- original streamer for feeding a sink from a file
streamer :: (IO S.ByteString -> IO r) -> IO r
streamer sink = withFile file ReadMode $ \h -> sink $ S.hGet h 10240

-- feed a lazy ByteString to sink    
lstreamer :: L.ByteString -> (IO S.ByteString -> IO r) -> IO r
lstreamer lbs sink = sink (return (L.toStrict lbs))

lstreamer类型检查,但可能并没有完全按照您想要的做。 每次接收器调用时,它仅返回相同的数据。 另一方面, S.hGet h ...最终将返回空字符串。

这是一个使用IORef来跟踪是否应该开始返回空字符串的解决方案:

import Data.IORef

mklstream :: L.ByteString -> (IO S.ByteString -> IO r) -> IO r
mklstream lbs sink = do
  ref <- newIORef False
  let fetch :: IO S.ByteString
      fetch = do sent <- readIORef ref
                 writeIORef ref True
                 if sent
                   then return S.empty
                   else return (L.toStrict lbs)
  sink fetch

这里fetch是获取一个块的动作。 第一次调用它,您将获得原始的惰性Bytestring(严格限制)。 后续调用将始终返回空字符串。

更新

一次发放少量款项的方法如下:

mklstream :: L.ByteString -> (IO S.ByteString -> IO r) -> IO r
mklstream lbs sink = do
  ref <- newIORef (L.toChunks lbs)
  let fetch :: IO S.ByteString
      fetch = do chunks <- readIORef ref
                 case chunks of
                   [] -> return S.empty
                   (c:cs) -> do writeIORef ref cs
                                return c
  sink fetch

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM