Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module CSV
- ( CSV
- , Record
- , Field
- , csv
- , parseCSV
- , parseCSVFromFile
- , parseCSVTest
- , printCSV
- )
- where
- import Text.Parsec
- import Text.Parsec.String
- import Text.Parsec.Error ( ParseError )
- import Data.List ( intersperse )
- -- | A CSV file is a series of records. According to the RFC, the
- -- records all have to have the same length. As an extension, I
- -- allow variable length records.
- type CSV = [Record]
- -- | A record is a series of fields
- type Record = [Field]
- -- | A field is a string
- type Field = String
- -- | A Parsec parser for parsing CSV files
- csv :: Parser CSV
- csv = do
- x <- record `sepEndBy` many1 (oneOf "\n\r")
- eof
- return x
- record :: Parser Record
- record = (quotedField <|> field) `sepBy` char ','
- field :: Parser Field
- field = many (noneOf ",\n\r\"")
- quotedField :: Parser Field
- quotedField = between (char '"') (char '"')
- $ many (noneOf "\"" <|> try (string "\"\"" >> return '"'))
- -- | Given a file name (used only for error messages) and a string to
- -- parse, run the parser.
- parseCSV :: FilePath -> String -> Either ParseError CSV
- parseCSV = parse csv
- -- | Given a file name, read from that file and run the parser
- parseCSVFromFile :: FilePath -> IO (Either ParseError CSV)
- parseCSVFromFile = parseFromFile csv
- -- | Given a string, run the parser, and print the result on stdout.
- parseCSVTest :: String -> IO ()
- parseCSVTest = parseTest csv
- -- | Given an object of type CSV, generate a CSV formatted
- -- string. Always uses escaped fields.
- printCSV :: CSV -> String
- printCSV records = unlines (printRecord `map` records)
- where
- printRecord = concat . intersperse "," . map printField
- printField f = "\"" ++ concatMap escape f ++ "\""
- escape '"' = "\"\""
- escape x = [x]
- unlines = concat . intersperse "\n"
Add Comment
Please, Sign In to add comment