From f5f0d00a75d642757964ae1e03bb59505424c2c3 Mon Sep 17 00:00:00 2001 From: 794404 Date: Wed, 15 Jul 2020 13:02:30 +0200 Subject: [PATCH] add write_csv & change skip_header to with_header option --- src/lib/csv.pl | 113 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 103 insertions(+), 10 deletions(-) diff --git a/src/lib/csv.pl b/src/lib/csv.pl index 16216166..b294b2b0 100644 --- a/src/lib/csv.pl +++ b/src/lib/csv.pl @@ -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: @@ -24,11 +27,34 @@ ?- 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, []). -- 2.54.0