Pure-CSV - Comma Separated Value Interface for the Pure Programming Language

Author: Eddie Rucker <erucker@bmc.edu>
Date: 2009-11-09
Copyright: 2008, 2009 by Eddie Rucker
License:3-clause BSD license, see the accompanying COPYING file for details

The CSV library provides an interface for reading and writing comma separated value files that is loosely based on Python's CSV module (http://docs.python.org/lib/module-csv.html).

Contents

1   Installation

Run make to compile the module and make install (as root) to install it in the Pure library directory. This requires GNU make. The make install step is only necessary for system-wide installation.

The make utility tries to guess your Pure installation directory and platform-specific setup. If it gets this wrong, you can set some variables manually. In particular, make install prefix=/usr sets the installation prefix, and make PIC=-fPIC or some similar flag might be needed for compilation on 64 bit systems. Please see the Makefile for details.

2   Usage

Data records are represented as lists of strings, integers, and doubles. Three predefined dialects are provided; RFC4180 (default for Windows), UNIX (default for Linux, *BSD, and Unix), and EXCEL; and procedures are provided to create other CSV dialects. See (http://www.ietf.org/rfc/rfc4180.txt) for more details about the RFC4180 standard.

Examples of reading and writing CSV files are provided in the file "samples.pure" located in the examples subdirectory.

2.1   Handling Errors

error msg
is an error handling term. Input that does not abide by dialect rules or records containing field types other than strings, integers, and doubles produce a special csv::error msg term, where msg is a string describing the particular error. Your application should either check for these or have csv::error defined to directly handle errors in some way (e.g., provide a default value, or raise an exception).

Examples

> using system, csv;
> csv::str [1%4, 1%3]; // rational numbers are not allowed
csv::error "field 1: invalid conversion type."
> /* Now, print a message and
>    perform an exit action on the error */
> csv::error msg = printf "CSV Error: %s\n" msg $$ exit 0;
> csv::str [1%4, 1%3];
CSV Error: field 1: invalid conversion type.
$

2.2   Creating Dialects

dialect list

creates a dialect from a list of dialect option pairs. Option pairs are denoted a=>b where a is the option and b is the option's value. The list of possible options and option values are presented below.

  • DELIMITER - Field delimiter.
    • Value - any string.
    • Default - ",".
  • ESCAPE - Embedded escape character.
    • Value - any string.
    • Default - "\"".
    • Notes - When reading, the escape character is dropped and the next char is inserted into the field. When writing, the escape character is written into the output stream.
  • QUOTE - Quote character.
    • Value - any string.
    • Default - "\"".
    • Notes - If embedded quotes are doubled, ESCAPE must equal the value of QUOTE. The dialect function will automatically set the ESCAPE string to that of QUOTE if ESCAPE is not specified in the dialect argument list.
  • QUOTING_STYLE - Sets the quoting style of strings and/or numbers.
    • Value - One of {QUOTE_ALL, QUOTE_STRINGS, QUOTE_EMBEDDED}.
    • Default - QUOTE_STRINGS.
  • LINETERMINATOR - Record termination value.
    • Value - any string.
    • Default: "\r\n".
  • SKIPSPACE - Skip leading white space flag.
  • Value - boolean {1=true, 0=false}.
  • Default - 1.
  • Note - Quoted fields always retain white space.

The following example illustrates the construction of a dialect for reading tab delimited files without quoted strings.

Examples

> using csv;
> /* Use the predefined EXCEL dialect */
> csv::list ("\"=\"\"004\",23\r\n", csv::EXCEL);
["=\"004",23]
> const d = csv::dialect [
>   csv::DELIMITER => "\t",
>   csv::QUOTING_STYLE => csv::QUOTE_EMBEDDED];
> csv::list ("\"John\tSmith\"\t23\t4.5\tfreshman", d);
["John\tSmith",23,4.5,"freshman"]
>

2.3   String and List Functions

str list|(list, dialect)
converts a list to a CSV formatted string. If the argument is a list, str converts the list using RFC 4180 rules (http://www.ietf.org/rfc/rfc4180.txt). If the argument is given as a tuple, then str converts the list using the rules specified in the user's dialect. A csv::error msg term is invoked if a fields contains data other than a string, integer, or a double types.

Examples

> using csv;
> csv::str [1,"",3.00,"bob \"plays drums\""];
"1,\"\",3,\"bob \"\"plays drums\"\"\"\n"
> const d = csv::dialect [csv::DELIMITER => "\t"];
> csv::str ([1,"",3.00,"bob \"plays drums\""], d);
"1\t\"\"\t3\t\"bob \"\"plays drums\"\"\"\n"
>
list string|(string, dialect)
creates a list of string or numeric fields from a CSV formatted string. If the argument is given as a string, then the conversion is performed using RFC 4180 rules (http://www.ietf.org/rfc/rfc4180.txt). If the argument is given as a tuple, then the conversion is performed according to the rules specified by the dialect. An invalidly formatted CSV string returns a csv::error msg term.

Examples

> using csv;
> csv::list "1,\"\",3,\"bob \"\"plays drums\"\"\"\n";
[1,"",3,"bob \"plays drums\""]
> const d = csv::dialect [csv::DELIMITER => "\t"];
> csv::list ("1\t\"\"\t3\t\"bob \"\"plays drums\"\"\"\n", d);
[1,"",3,"bob \"plays drums\""]
>

2.4   File Reading Functions

fgets file|(file, dialect)
is equivalent to csv::list except that reading is from a file. The file must first be opened using fopen which is defined in the system library (system.pure).
fget file|(file, dialect)
reads a whole file and returns a list of records. This procedure should only be used on data files that are small enough to fit in the computer's primary memory.

Examples

> using system, csv;
> /* Write a file to test */
> let f = fopen "test.csv" "w";
> csv::fput [[1,"a"], [2,"b"], [3,"c"]] f;
()
> fclose f;
0
> let f = fopen "test.csv" "r";
> csv::fgets f;
[1,"a"]
> fclose f;
0
>

2.5   File Writing Functions

When modifying CSV files that will be imported into Microsoft Excel, fields with significant leading 0s should be written using a "=""0...""" formatting scheme. This same technique will work for preserving leading space too. Again, this quirk should only be necessary for files to be imported into MS Excel.

fputs list file|(file, dialect)
is equivalent to csv::str except that writing is to a file. The file must first be opened using fopen which can be found in the system library.
fput list file|(file, dialect)
writes a list of records to a file. Each record is converted according to the rules stated in the csv::str procedure.

Examples

> using system, csv;
> /* Write a file to test */
> let f = fopen "test.csv" "w";
> csv::fput [[1,"a"], [2,"b"], [3,"c"]] f;
()
> fclose f;
0
> let f = fopen "test.csv" "r";
> /* Read the first record */
> csv::fgets f;
[1,"a"]
> /* Read the next record */
> csv::fgets f;
[2,"b"]
> fclose f;
0
>