管道-管道中的多个输出文件

雅各布·王

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

这是我在想的管道:

  • 源:使用Conduit.Binary.sourceFile从输入中读取
  • 管道:取一个ByteString,产生[ByteString]
  • 接收器:从管道中获取[ByteString],并将每个ByteString(在[ByteString]中)写入其相应的文件。(例如,如果我们的输入[ByteString]被称为bsl,那么bsl !! 0它将被写入文件0,bsl !! 1文件1,依此类推)

我在这里发现了有关多个输入文件的问题,但在这种情况下,整个管道对每个输入文件只运行一次,而对于我的程序,我正在向管道中的多个输出文件进行写入

我还在这里浏览Conduit源代码,看我是否可以自己实现multiSinkFile,但是我对ConsumerFile的sinkFile类型有些困惑,如果我尝试更深入地研究它,那就更是如此...(我是还是个初学者)

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

任何提示表示赞赏!

澄清度

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

(因此,我们有输入文件srcFile和输出文件outFile0outFile1以及outFile2

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

编辑:

谢谢您的回答。我花了一些时间来了解ZipSinks等的最新情况,并且编写了一个简单的测试程序,该程序接受源文件的输入并将其简单地写入3个输出文件。希望这会在将来对其他人有所帮助。

{-# 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
迈克尔·斯诺曼

有多种方法可以执行此操作,具体取决于您是要动态增加要写入的文件数,还是只是保持固定的数目。这是一个带有固定文件列表的示例:

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns      #-}
import           ClassyPrelude.Conduit
import           Safe                  (atMay)

idxSinkFile :: MonadResource m
            => (Int -> FilePath)
            -> Int
            -> Consumer [ByteString] m ()
idxSinkFile mkFP idx =
    concatMapC (flip atMay idx) =$= sinkFile fp
  where
    fp = mkFP idx

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

someFunc :: ByteString -> [ByteString]
someFunc (decodeUtf8 -> x) = map encodeUtf8 [x, toUpper x, toLower x]

mkFP :: Int -> FilePath
mkFP 0 = "file0.txt"
mkFP 1 = "file1.txt"
mkFP 2 = "file2.txt"

src :: Monad m => Producer m ByteString
src = yieldMany $ map encodeUtf8 $ words "Hello There World!"

main :: IO ()
main = do
    let indices = [0..2]
    runResourceT $ src $$ mapC someFunc =$ sinkMultiFiles mkFP indices
    forM_ indices $ \idx -> do
        let fp = mkFP idx
        bs <- readFile fp
        print (fp, bs :: ByteString)

您可以在FP School of Haskell上在线尝试

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

从命令行管道输出中写文件?

来自分类Dev

在PowerShell中将所有写入输出通过管道传输到相同的输出文件

来自分类Dev

输出前管道错误

来自分类Dev

复制管道输出

来自分类Dev

在sklearn管道中合并的多个管道?

来自分类Dev

管道:写入管道的前面

来自分类Dev

保留管道输出的颜色

来自分类Dev

R中具有多个输出的管道和If语句

来自分类Dev

Azure DevOps管道-输出文件的自定义名称

来自分类Dev

管道comand列的输出

来自分类Dev

从命令行管道输出中写文件?

来自分类Dev

管道-管道中的多个输出文件

来自分类Dev

我想将输出管道传输到bash中的多个文件

来自分类Dev

如何使用通过批处理管道传递的两个命令中的相同输出文件

来自分类Dev

管道输出到别名

来自分类Dev

管道的gnuplot输出

来自分类Dev

从程序仅输出到文件的管道输出

来自分类Dev

输出前管道错误

来自分类Dev

管道输出到grep

来自分类Dev

将systemd输出管道到文件中

来自分类Dev

如何使用管道指定输出文件名?

来自分类Dev

管道命令输出转换?

来自分类Dev

选择管道的输出

来自分类Dev

Bash在出现管道错误的情况下保留原始管道输出文件的一线方式?

来自分类Dev

用管道输送并将其他输出写入输出文件

来自分类Dev

管道到标准输出

来自分类Dev

puppeteer 的管道输出

来自分类Dev

管道 ssh sudo 的输出

来自分类Dev

具有多个输入/输出的 sklearn 管道