2014-11-13 7 views
0

У меня есть CSV-файл, полный зарегистрированных данных, которые я хотел бы обработать в Haskell. Данные в CSV-файле находятся в шестнадцатеричном формате. Когда я читаю его в Haskell, у меня есть строки, такие как «0xFF5FFFC8EC5FFEDF», который представляет 8 байтов данных.Манипулирование шестнадцатеричными данными в Haskell

Чтобы обработать данные, я хотел бы преобразовать строку в тип данных, который позволит мне выполнять бит twiddling (побитовый AND, OR и XOR). Затем, когда я закончил, я хотел бы преобразовать окончательный результат обратно в шестнадцатеричное sting, чтобы я мог записать его в файл.

Это легко сделать в Haskell? На каких модулях я должен смотреть?

+0

Как долго ваши шестнадцатеричные строки? Будут ли они всегда вписываться в 64-битный int, или они могут быть длиннее? – ErikR

ответ

2

Вы можете использовать read для синтаксического анализа или плавания. Это в Prelude, поэтому вы можете использовать его без каких-либо дополнительных модулей.

Try:

a = "0xFF5FFFC8EC5FFEDF" 
b = read a::Double 

(это дает Ь = 1.8401707840883393e19)

Кроме того, для разбора CSV, вы можете Aswell сделать свои собственные функции, чтобы сделать это. У меня всего неделю назад был написан простой синтаксический анализатор CSV.

module CSVUtils 
    (parseCSV, showCSV 
    , readCSV , writeCSV 
    , colFields 
    , Separator, Document 
    , CSV  , Entry 
    , Field 
    ) 
where 

import Data.Char 
import Data.List 
{- 
A simple utility for working with CSV (comma-separated value) files. These 
are simple textual files where fields are delimited with a character (usually a comma 
or a semicolon). It is required that the CSV document is well-formed, i.e., that 
it contains an equal number of fields per row. 
-} 
type Separator = String 
type Document = String 
type CSV = [Entry] 
type Entry = [Field] 
type Field = String 

doc = "John;Doe;15\nTom;Sawyer;12\nAnnie;Blake;20" 
brokenDoc = "One;Two\nThree;Four;Five" 
{- 
(a) Takes a separator and a string representing a CSV document and returns a 
CSV representation of the document. 
-} 
-- !! In the homework text is said Separator is going to be Char and now the type is String 
-- !! so I'm just going to take head 
parseCSV :: Separator -> Document -> CSV 
parseCSV sep doc 
    | (head sep) `notElem` doc      = error $ "The character '"++sep++"' does not occur in the text" 
    | 1 /= length (nub (map length (lines doc))) = error $ "The CSV file is not well-formed"    
    | otherwise         = [splitOn sep wrd | wrd <- lines doc ] 
{- 
(b) Takes a separator and a CSV representation of 
a document and creates a CSV string from it. 
-} 
showCSV :: Separator -> CSV -> Document 
showCSV sep = init . unlines . map (intercalate sep) 
{- 
(c) Takes a CSV document and a field number 
and returns a list of fields in that column. 
-} 
colFields :: Int -> CSV -> [Field] 
colFields n csv = [ if length field > n 
        then field !! n 
        else error $ "There is no column "++(show n)++" in the CSV document" 

        | field <- csv] 
{- 
(d) Takes a file path and a separator and returns the CSV representation of the file. 
-} 
readCSV :: Separator -> FilePath -> IO CSV 
readCSV sep path = do 
    file <- readFile path 
    return $ parseCSV sep file 

{- 
(e) Takes a separator, a file path, and a CSV document and writes the document into a file. 
The return type of writeCSV is a special case of IO { we need to wrap an impure 
action, but do not actually have to return anything when writing. Thus, we 
introduce(), or the unit type, which holds no information (consider it a 0- 
tuple). 
-} 
writeCSV :: Separator -> FilePath -> CSV -> IO() 
writeCSV sep path csv = writeFile path (showCSV sep csv) 
+0

Я не знал этого о 'read'. – ErikR

+0

;) Да, читать довольно круто. Просто не забудьте указать тип с :: – ditoslav

+0

Я думаю, вы должны использовать 'Word64' вместо' Double' ... – Cactus

0

Я собираюсь предположить, что ваши двоичные данные могут быть произвольной длины. Вещи могут быть упрощены, если, например, ваши двоичные данные вписываются в Int64.

Я буду рекомендовать следующие библиотеки и модули:

  • cassava для CSV разборе
  • bytestring для строкового типа
  • base16-bytestring для преобразования в/из шестнадцатеричных строк
  • Data.Bits для поразрядных операций по байтам, символам, целям и т. д.

Для примера того, как выполнять битовые операции на байтовых строк, смотрите в конце этого урока в Школе Haskell:

https://www.fpcomplete.com/school/to-infinity-and-beyond/pick-of-the-week/bytestring-bits-and-pieces

Для примеров того, как использовать cassava, обратите внимание на examples каталог исходного репозитория:

https://github.com/tibbe/cassava/tree/master/examples

Смежные вопросы