Ich lese eine CSV-Datei mit Pipes-CSV-Bibliothek. Ich möchte die erste Zeile lesen und den Rest später lesen. Leider nach Pipes.Prelude.head Funktion zurück. Das Rohr wird irgendwie geschlossen. Gibt es eine Möglichkeit, den Kopf des CSV zuerst zu lesen und den Rest später zu lesen.Erste Zeile aus einer CSV-Datei mit Pipes-Csv lesen
import qualified Data.Vector as V
import Pipes
import qualified Pipes.Prelude as P
import qualified System.IO as IO
import qualified Pipes.ByteString as PB
import qualified Data.Text as Text
import qualified Pipes.Csv as PCsv
import Control.Monad (forever)
showPipe :: Proxy() (Either String (V.Vector Text.Text))() String IO b
showPipe = forever $ do
x::(Either String (V.Vector Text.Text)) <- await
yield $ show x
main :: IO()
main = do
IO.withFile "./test.csv"
IO.ReadMode
(\handle -> do
let producer = (PCsv.decode PCsv.NoHeader (PB.fromHandle handle))
headers <- P.head producer
putStrLn "Header"
putStrLn $ show headers
putStrLn $ "Rows"
runEffect (producer>->
(showPipe) >->
P.stdoutLn)
)
Wenn wir den Header nicht lesen zuerst, können wir ganze csv ohne Probleme lesen:
main :: IO()
main = do
IO.withFile "./test.csv"
IO.ReadMode
(\handle -> do
let producer = (PCsv.decode PCsv.NoHeader (PB.fromHandle handle))
putStrLn $ "Rows"
runEffect (producer>->
(showPipe) >->
P.stdoutLn)
)
P.next war Präfekt Lösung für meinen Fall. Danke auch für die Anzeige der Kartenversion von showPipe. – yilmazhuseyin
Auch die Entweder mit P.concat zu entfernen war wirklich ein schöner Trick. – yilmazhuseyin