]> Repositorios git - scryer-prolog.git/commitdiff
add write_csv & change skip_header to with_header option
author794404 <[email protected]>
Wed, 15 Jul 2020 11:02:30 +0000 (13:02 +0200)
committer794404 <[email protected]>
Wed, 15 Jul 2020 11:02:30 +0000 (13:02 +0200)
src/lib/csv.pl

index 16216166c1942fe413c718567b93b46ca52d06fc..b294b2b09d44bc092b29031a33090a49e3928c41 100644 (file)
@@ -1,9 +1,12 @@
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   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
 
@@ -16,7 +19,7 @@
 
   * 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)).
@@ -49,6 +75,74 @@ option_extends([X | Y], Opt0, Opt) :-
   ; 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) },
@@ -124,17 +218,16 @@ rows(R, 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, []).