2017-01-17 5 views
4

コンジットを使用してテキストを分割するときに問題が発生します。Conduit with Windowsで分割する

私が扱っているソースデータは残念ながら、同じファイル内に\r\n\nの両方のシーケンスを含む行末とは一貫していません。

私はいくつかの例では、末尾\rを私に残した、Data.Conduit.Binarylines機能を見つけたが、それシングルバイトで「分割」、(賢明に十分\n、)しています。

現在の実装では、それがないように動作する、と私は私が一緒に解決策のいくつかの種類をハック可能性がほとんど確信していますが、これを行うには、私は考えることができる唯一の方法は、のようなものになるだろう、なぜ私が理解:

lines' = do 
    loop $ T.pack "" 
    where loop acc = do 
     char <- await 
     case char of 
      Nothing -> return() 
      Just x -> do 
      case (isOver $ acc `T.append` x) of 
        (True,y) -> yield y 
        (False,y) -> loop y 
        where isOver n 
          | (T.takeEnd 2 n == _rLn) = (True, T.dropEnd 2 n) 
          | (T.takeEnd 1 n == _Ln) = (True, T.dropEnd 1 n) 
          | otherwise    = (False,n) 
          where _rLn = T.pack $! "\r\n" 
           _Ln = T.pack $! "\n" 

...これは控えめで、クルージングで、ひどく遅く感じます。

私が実際にやる必要があるのは、最後に読み込まれた文字が\rだったとしたら「覚えている」ので、最後の2文字をチェックするのは間違っていますが、それを行うには賢明な方法は考えられません。

この問題の解決策を知っている人はいますか?

答えて

4

ホイールを改造しないでください!私たちはまだconduit-combinatorsを使って、もっときれいなものを作ることができます。序文として、あなたの\rの値が、改行の前にあることを除いて決して起こらない場合は、それらをまっすぐにフィルタリングすることができます。つまり、私はあなたのケースがより一般的であると仮定しようとしています。\rの値の後には\nの値を取り除きたいだけです。

考えてみましょうslidingWindowCを使用して2つの文字チャンクを取得し、これらのチャンクを最初の文字にマッピングします。ただし、文字が"\r\n"でない場合は両方をドロップします。その後、改行が続く\rをすべて削除したので、コンジットlinesUnboundedCを使用できます。明らかData.Conduit.Text

{-# LANGUAGE TypeFamilies, FlexibleContexts #-} 

import Data.Text (Text, singleton, empty) 
import Data.MonoTraversable (Element, MonoFoldable) 
import Conduit 

main = runConduitRes $ (sourceFile "file.txt" :: Producer (ResourceT IO) Text) 
        .| linesUnboundedC' 
        .| printC 

-- | Converted a chunked input of characters into lines delimited by \n or \r\n 
linesUnboundedC' 
    :: (Element a ~ Char, MonoFoldable a, Monad m) => ConduitM a Text m() 
linesUnboundedC' = concatMapC id 
       .| slidingWindowC 2 
       .| mapC (\[email protected][c,_] -> if cs == "\r\n" then empty else singleton c) 
       .| linesUnboundedC 
+0

これはすばらしい答えです。「slidingWindow」についてのヒントについては、ありがたいことです。これは、私がまだ知りませんでしたいくつかの他の問題を解決します。 しかし、明らかに 'Data.Conduit.Text'パッケージの' foldLines'関数は、このユースケースをかなりうまく扱うことが分かっています。つまり、「ホイールを再作成しないでください」と思います。それを「正しい」答えとするつもりです。 –

+0

@IronGremlin Nice find!それを確かに行ってください - それはかなり速いはずです。 – Alec

4

が記載されているように、正確に動作する機能、foldLinesを有しています。

関連する問題