/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Predicates for parsing CSV data
- Only two options are provided with default values :
- - token_separator(',')
- - skip_header(false)
+
+ Read csv files
+
+ Only two options with default values :
+ - token_separator(',')
+ - with_header(true)
Examples
* with some options:
- ?- phrase(parse_csv(Data, [skip_header(true),token_separator(';')]), "col1;col2;col3,col4\none;2;;three").
+ ?- phrase(parse_csv(Data, [with_header(false), token_separator(';')]), "one;2;;three").
Data = frame([],[["one",2,[],"three"]]).
* parsing a csv file:
?- use_module(library(csv)).
?- use_module(library(pio)).
?- phrase_from_file(parse_csv(frame(Header, Rows)), './test.csv').
+
+
+ Write csv files
+
+ Four options with default values :
+ - line_separator('\n')
+ - token_separator(',')
+ - with_header(true)
+ - null_value(empty)
+
+ Examples
+
+ * writing a csv file:
+
+ ?- use_module(library(csv)).
+ ?- write_csv('./test.csv', frame(["col1","col2","col3","col4"], [["one",2,[],"three"]])).
+
+ * with some options
+
+ ?- use_module(library(csv)).
+ ?- write_csv('./test.csv', frame(["col1","col2","col3","col4"], [["one",2,[],"three"]]), [with_header(false), line_separator('\r\n'), token_separator(';'), null_value('\\N')]).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- module(csv, [
parse_csv//1,
- parse_csv//2
+ parse_csv//2,
+ write_csv/2,
+ write_csv/3
]).
:- use_module(library(dcgs)).
; option_extends(Y, [X | Opt0], Opt) ).
+%% -- write --
+
+
+escaped_field([], []).
+escaped_field(['"' | Y], ['"', '"' | R]) :-
+ escaped_field(Y, R).
+escaped_field([X | Y], [X | R]) :-
+ X \== '"',
+ escaped_field(Y, R).
+
+
+ensure_escaped(Field, Field) :-
+ (atom(Field); integer(Field); float(Field)).
+ensure_escaped([X | Y], Field) :-
+ escaped_field([X | Y], Field).
+
+
+write_field(Field, Opt) :-
+( Field \== [] ->
+ ensure_escaped(Field, Field0),
+ write(Field0)
+ ; option(null_value(Null_Value), Opt),
+ ( Null_Value == empty -> true
+ ; write(Null_Value))).
+
+
+write_row([Field], Opt) :-
+ write_field(Field, Opt).
+write_row([Field, X | Y], Opt) :-
+ write_field(Field, Opt),
+ option(token_separator(Tk_Sep), Opt),
+ write(Tk_Sep),
+ write_row([X | Y], Opt).
+
+
+write_rows([Row], Opt) :-
+ write_row(Row, Opt).
+write_rows([Row, X | Y], Opt) :-
+ option(line_separator(Line_Sep), Opt),
+ write_row(Row, Opt),
+ write(Line_Sep),
+ write_rows([X | Y], Opt).
+
+
+write_csv(File_Name, frame(Header, Rows), Opt) :-
+ option_extends(Opt, [
+ null_value(empty),
+ token_separator(','),
+ with_header(true),
+ line_separator('\n')
+ ], Opt0),
+ open(File_Name, write, Out),
+ set_output(Out),
+ option(with_header(With_Header), Opt0),
+ ( With_Header == true ->
+ write_row(Header, Opt0),
+ option(line_separator(Line_Sep), Opt0),
+ write(Line_Sep)
+ ; true),
+ write_rows(Rows, Opt0),
+ close(Out),
+ set_output(user_output).
+write_csv(File_Name, Frm) :-
+ write_csv(File_Name, Frm, []).
+
+
+%% -- read --
+
tokens([], Opt), [Tk_Sep] -->
{ option(token_separator(Tk_Sep), Opt) },
parse_csv(frame(Header, Rows), Opt) -->
{ option_extends(Opt, [
- skip_header(false),
+ with_header(true),
token_separator(',')
], Opt0)
},
- ( { member(skip_header(false), Opt0) } ->
+ ( { option(with_header(With_Header), Opt0),
+ With_Header == true } ->
row(Header, Opt0),
{ Header \== [[]] },
end_token
- ; row(_, Opt0),
- end_token,
- { Header = [] }),
+ ; { Header = [] }),
rows(Rows, Opt0).
parse_csv(R) -->
parse_csv(R, []).