gpt4 book ai didi

haskell - 管道 - 管道内的多个输出文件

转载 作者:行者123 更新时间:2023-12-04 05:50:23 30 4
gpt4 key购买 nike

我正在编写一个程序,其中输入文件被拆分为多个文件(Shamir 的 secret 共享方案)。

这是我想象的管道:

  • 来源:使用 Conduit.Binary.sourceFile 从输入中读取
  • 导管:获取一个 ByteString,产生 [ByteString]
  • 水槽:从管道中获取 [ByteString],并将每个 ByteString(在 [ByteString] 中)写入其相应的文件。 (假设我们的输入 [ByteString] 被称为 bsl,那么 bsl !! 0 将被写入文件 0,bsl !! 1 被写入文件 1 等等)

  • 我发现了一个关于多个输入文件的问题 here ,但在他们的情况下,整个管道为每个输入文件运行一次,而对于我的程序,我正在写入管道中的多个输出文件。

    我也在查看 Conduit 源代码 here看看我是否可以自己实现一个 multiSinkFile,但是我对 sinkFile 的 Consumer 类型有点困惑,如果我尝试更深入地挖掘,更是如此......(我还是个初学者)

    所以,问题是,我应该如何实现像 multiSinkFile 这样的函数,它允许将多个文件作为接收器的一部分写入?

    任何提示表示赞赏!

    澄清

    假设我们要对包含二进制值“ABCDEF”(分为 3 部分)的文件进行 Shamir 的 secret 共享。

    (所以我们有我们的输入文件 srcFile 和我们的输出文件 outFile0outFile1outFile2 )

    我们首先从文件中读取“ABC”,然后进行处理,这将为我们提供一个列表,例如 ["133", "426", "765"]。 .所以 "133"将写入 outFile0 , "426"outFile1"765"outFile2 .然后我们从 srcFile 中读取“DEF” ,对其进行处理,并将相应的输出写入每个输出文件。

    编辑:

    谢谢您的回答。我花了一些时间来了解 ZipSinks 等的情况,并且我编写了一个简单的测试程序,它接受源文件的输入并将其简单地写入 3 个输出文件。希望这将在 future 对其他人有所帮助。
    {-# LANGUAGE NoImplicitPrelude #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE OverloadedStrings #-}
    import ClassyPrelude.Conduit
    import Safe (atMay)
    import Text.Printf
    import Filesystem.Path.CurrentOS (decodeString, encodeString)
    import Control.Monad.Trans.Resource (runResourceT, ResourceT(..))

    -- get the output file name given the base (file) path and the split number
    getFileName :: FilePath -> Int -> FilePath
    getFileName basePath splitNumber = decodeString $ encodeString basePath ++ "." ++ printf "%03d" splitNumber

    -- Get the sink file, given a filepath generator (that takes an Int) and the split number
    idxSinkFile :: MonadResource m
    => (Int -> FilePath)
    -> Int
    -> Consumer [ByteString] m ()
    idxSinkFile mkFP splitNumber =
    concatMapC (flip atMay splitNumber) =$= sinkFile (mkFP splitNumber)

    sinkMultiFiles :: MonadResource m
    => (Int -> FilePath)
    -> [Int]
    -> Sink [ByteString] m ()
    sinkMultiFiles mkFP splitNumbers = getZipSink $ otraverse_ (ZipSink . idxSinkFile mkFP) splitNumbers

    simpleConduit :: Int -> Conduit ByteString (ResourceT IO) [ByteString]
    simpleConduit num = mapC (replicate num)

    main :: IO ()
    main = do
    let mkFP = getFileName "test.txt"
    splitNumbers = [0..2]
    runResourceT $ sourceFile "test.txt" $$ simpleConduit (length splitNumbers) =$ sinkMultiFiles mkFP splitNumbers

    最佳答案

    一种可能性是让您的算法输出类似于 (Int, ByteString) 的内容。 , 其中 Int是指定输出文件的索引(当然您可以使用任何其他类型作为键)。这样,管道可以决定它想要将其输出附加到哪个文件。

    import Data.Conduit
    import qualified Data.Conduit.List as C
    import qualified Data.Foldable as F

    -- | Filter only pairs tagged with the appropriate key.
    filterInputC :: (Monad m, Eq k) => k -> Conduit (k, a) m a
    filterInputC idx = C.filter ((idx ==) . fst) =$= C.map snd

    -- | Prepend a given sink with a filter.
    filterInput :: (Monad m, Eq k) => k -> Sink a m r -> Sink (k, a) m r
    filterInput idx = (filterInputC idx =$)

    -- | Given a list of sinks, create a single sink that directs received values
    -- depending on the index.
    multiSink_ :: (Monad m) => [Sink a m ()] -> Sink (Int, a) m ()
    multiSink_ = getZipSink . F.sequenceA_ . fmap ZipSink
    . zipWith filterInput [0..]

    更新:以下示例显示了 multiSink_可以使用(测试接收器只是将所有内容打印到带有适当前缀的标准输出,而不是写入文件)。
    -- | A testing sink that just prints its input, marking it with
    -- a given prefix.
    testSink :: String -> Sink String IO ()
    testSink prefix = C.mapM_ (putStrLn . (prefix ++))

    -- | An example that produces indexed output.
    testSource :: (Monad m) => Source m (Int, String)
    testSource = do
    yield (0, "abc")
    yield (0, "def")
    yield (1, "opq")
    yield (0, "0")
    yield (1, "1")
    yield (2, "rest")

    main :: IO ()
    main = testSource $$ multiSink_ (map testSink ["1: ", "2: ", "3: "])

    关于haskell - 管道 - 管道内的多个输出文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23169458/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com