管道检查文件头

时间:2017-10-27 08:14:54

标签: haskell header bytestring conduit

我想在我读取二进制文件的设置中使用Either String,检查它是否有正确的标题,然后处理文件中的其余数据。

尝试编写一个检查标题的管道,然后将其余数据流式传输到以下管道,我遇到了麻烦。我让他们住在Condiut.Attoparsec monad中进行一些异常处理。这是代码的简化版本(我知道有一个import Conduit (ConduitM, mapC, mapM_C, takeWhileCE) import Data.ByteString.Conversion (toByteString') separator :: ByteString separator = toByteString' '#' check :: ByteString -> Either String () confirmHeader :: ConduitM ByteString ByteString (Either String) () confirmHeader = do takeWhileC (/= separator) .| mapM_C check mapC id 模块,但现在我想自己写一下):

separator

ByteString是一个预定义的mapC id,表示标题的结尾。如果标题检出,则行check应该传递流的其余部分。我遗漏了runConduit $ yield (toByteString' "header#rest") .| confirmHeader .| sinkList 的非重要细节。

检查标题的部分有效。然而,最后一行,除了看起来不优雅和非惯用之外,不起作用。运行像

这样的东西
Right []

正如我所希望的那样,提供Right ["rest"]而不是var notButtonDivs = $('.test').filter(function(){ return $(this).find('div').length == $(this).find('div:has(button)').length }) 。有任何想法吗?

1 个答案:

答案 0 :(得分:1)

您的#include <stdio.h> #include <string.h> int main() { FILE * ifp; char filename[20]; int i=0; int keyval[7]; int key[7]; int counter; printf("What is the name of the text file?\n"); gets(filename); ifp = fopen(filename, "r"); if (ifp == NULL){ printf("Error the file could not be opened.\n"); return 0; } printf("In order to get my treasure you'll have to figure out which of my 100 keys are used in the 7 locks!\n"); while(!feof(ifp)){ fscanf(ifp, "%d",keyval[i] ); printf("%d", keyval[i]); i++; } printf("Which keys will you use?"); for(counter=0; counter <8; counter++){ scanf("%d",key[counter]); } if(keyval[1]= key[1], keyval[2]= key[2], keyval[3]= key[3], keyval[4]=key[4], keyval[5]=key[5], keyval[6]=keyval[6], keyval[7]=key[7]){ printf("You've opened my treasure and found a map to the rest of the treasure on the island! Haha!\n"); } fclose(ifp); return 0; } 占据了整个takeWhileC (/= separator):它不会在ByteString的大块上工作!您可以使用ByteString处理流的各个字节。下面的代码“按预期”工作,我相信。

Data.Conduit.Binary

输出:

module Main (main) where

import           Conduit
import           Data.ByteString (ByteString)
import           Data.ByteString.Conversion (toByteString')
import           Data.Char (ord)
import qualified Data.Conduit.Binary as B
import           GHC.Word (Word8)

separator :: Word8
separator = toEnum $ ord '#'

check :: ByteString -> Either String ()
check _ = Right ()

confirmHeader :: ConduitM ByteString ByteString (Either String) ()
confirmHeader = do
  B.takeWhile (/= separator) .| mapM_C check
  B.drop 1 -- drop separator which stayed in stream
  mapC id

main :: IO ()
main = print . runConduit $
  yield (toByteString' "header#rest") .| confirmHeader .| sinkList