Allow '-' to mean read from stdin.
[ocaml-csv.git] / csv.mli
1 (** csv.mli - comma separated values parser
2   *
3   * $Id: csv.mli,v 1.10 2006-11-24 15:49:24 rich Exp $
4   *)
5
6 type t = string list list
7 (** Representation of CSV files. *)
8
9 exception Bad_CSV_file of string
10 (** Badly formed CSV files throw this exception. *)
11
12 val lines : t -> int
13 (** Work out the number of lines in a CSV file. *)
14
15 val columns : t -> int
16 (** Work out the (maximum) number of columns in a CSV file. Note that each
17   * line may be a different length, so this finds the one with the most
18   * columns.
19   *)
20
21 val load_in : ?separator:char -> in_channel -> t
22 (** Load a CSV file.
23   * @param chan Input file stream
24   *)
25
26 val load : ?separator:char -> string -> t
27 (** Load a CSV file.
28   * @param filename CSV filename.
29   * If [filename] is ["-"] then load from [stdin].
30   *)
31
32 val load_rows : ?separator:char -> (string list -> unit) -> in_channel -> unit
33 (** For very large CSV files which cannot be processed in memory at once,
34   * this function is appropriate. It parses the input one row at a time and
35   * calls your function once for each row.
36   *
37   * Note that if you CSV file contains cells which have embedded
38   * line feeds, then it is non-trivial to parse these lines and
39   * pass them correctly to [load_rows].
40   *
41   * @param f Callout function.
42   * @param chan Input file stream.
43   *)
44
45 val trim : ?top:bool -> ?left:bool -> ?right:bool -> ?bottom:bool -> t -> t
46 (** This takes a CSV file and trims empty cells.
47   *
48   * All four of the option arguments ([~top], [~left], [~right], [~bottom])
49   * default to [true].
50   *
51   * The exact behaviour is:
52   *
53   * [~right]: If true, remove any empty cells at the right hand end of
54   * any row.  The number of columns in the resulting CSV structure will
55   * not necessarily be the same for each row.
56   *
57   * [~top]: If true, remove any empty rows (no cells, or containing just empty
58   * cells) from the top of the CSV structure.
59   *
60   * [~bottom]: If true, remove any empty rows from the bottom of the
61   * CSV structure.
62   *
63   * [~left]: If true, remove any empty columns from the left of the
64   * CSV structure.  Note that [~left] and [~right] are quite different:
65   * [~left] considers the whole CSV structure, whereas [~right] considers
66   * each row in isolation.
67   *)
68
69 val square : t -> t
70 (** Make the CSV data "square" (actually rectangular).  This pads out
71   * each row with empty cells so that all rows are the same length as
72   * the longest row.  After this operation, every row will have length
73   * {!Csv.columns}.
74   *)
75
76 val is_square : t -> bool
77 (** Return true iff the CSV is "square" (actually rectangular).  This
78   * means that each row has the same number of cells.
79   *)
80
81 val set_columns : int -> t -> t
82 (** [set_columns cols csv] makes the CSV data square by forcing the width
83   * to the given number of [cols].  Any short rows are padded with blank
84   * cells.  Any long rows are truncated.
85   *)
86
87 val set_rows : int -> t -> t
88 (** [set_rows rows csv] makes the CSV data have exactly [rows] rows
89   * by adding empty rows or truncating rows as necessary.
90   *
91   * Note that [set_rows] does not make the CSV square.  If you want it
92   * to be square, call either {!Csv.square} or {!Csv.set_columns} after.
93   *)
94
95 val set_size : int -> int -> t -> t
96 (** [set_size rows cols csv] makes the CSV data square by forcing the
97   * size to [rows * cols], adding blank cells or truncating as necessary.
98   * It is the same as calling [set_columns cols (set_rows rows csv)]
99   *)
100
101 val sub : int -> int -> int -> int -> t -> t
102 (** [sub r c rows cols csv] returns a subset of [csv].  The subset is
103   * defined as having top left corner at row [r], column [c] (counting
104   * from [0]) and being [rows] deep and [cols] wide.
105   *
106   * The returned CSV will be square.
107   *)
108
109 val compare : t -> t -> int
110 (** Compare two CSV files for equality, ignoring blank cells at the end
111   * of a row, and empty rows appended to one or the other.  This is
112   * "semantic" equality - roughly speaking, the two CSV files would
113   * look the same if opened in a spreadsheet program.
114   *)
115
116 val concat : t list -> t
117 (** Concatenate CSV files so that they appear side by side, arranged
118   * left to right across the page.  Each CSV file (except the final
119   * one) is first squared.
120   *
121   * (To concatenate CSV files so that they appear from top to bottom,
122   * just use {!List.concat}).
123   *)
124
125 val to_array : t -> string array array
126 val of_array : string array array -> t
127 (** Convenience functions to convert to and from a matrix representation.
128   * [to_array] will produce a ragged matrix (not all rows will have the
129   * same length) unless you call {!Csv.square} first.
130   *)
131
132 val associate : string list -> t -> (string * string) list list
133 (** [associate header data] takes a block of data and converts each
134   * row in turn into an assoc list which maps column header to data cell.
135   *
136   * Typically a spreadsheet will have the format:
137   * {v
138   *   header1   header2   header3
139   *   data11    data12    data13
140   *   data21    data22    data23
141   *     ...
142   * v}
143   *
144   * This function arranges the data into a more usable form which is
145   * robust against changes in column ordering.  The output of the
146   * function is:
147   * {v
148   *   [ ["header1", "data11"; "header2", "data12"; "header3", "data13"];
149   *     ["header1", "data21"; "header2", "data22"; "header3", "data23"];
150   *     etc. ]
151   * v}
152   *
153   * Each row is turned into an assoc list (see [List.assoc]).
154   *
155   * If a row is too short, it is padded with empty cells ([""]).  If
156   * a row is too long, it is truncated.
157   *
158   * You would typically call this function as:
159   *
160   * {v
161   * let header, data = match csv with h :: d -> h, d | [] -> assert false;;
162   * let data = Csv.associate header data;;
163   * v}
164   *
165   * The header strings are shared, so the actual space in memory consumed
166   * by the spreadsheet is not much larger.
167   *)
168
169 val print : ?separator:char -> t -> unit
170 (** Print string list list - same as [save_out stdout] *)
171
172 val save_out : ?separator:char -> out_channel -> t -> unit
173 (** Save string list list to a channel. *)
174
175 val save : ?separator:char -> string -> t -> unit
176 (** Save string list list to a file. *)
177
178 val print_readable : t -> unit
179 (** Print the CSV data to [stdout] in a human-readable format.  Not much
180   * is guaranteed about how the CSV is printed, except that it will be
181   * easier to follow than a "raw" output done with {!Csv.print}.  This is
182   * a one-way operation.  There is no easy way to parse the output of
183   * this command back into CSV data.
184   *)
185 val save_out_readable : out_channel -> t -> unit
186 (** As for {!Csv.print_readable}, allowing the output to be sent to a channel.
187   *)