QforMortals3/File I-O 101
1.18 File I/O 101
For this section we need to introduce the other q primitive text data type, called char. A single ASCII character is represented as that character in double quotes. Here are some examples.
q)"a" _ q)" " _ q)"_" _
The char "a" is an atom but is ‘’’not’’’ the same as its symbol cousin `a.
Things get sticky with a simple list of char. Enter such a list in general form and observe the simplified display echoed on the console.
q)("s";"t"; "r"; "i"; "n"; "g") ”string”
A simple list of char looks like a string from traditional languages and is even called a string in q. But this string is ‘’’not’’’ an atom or even a first class entity in q; it is a list having count 6. And it should ‘’’not’’’ be confused with its symbol cousin `string, which is an atom having count 1.
q)count "string" _ q)count `string _
With these preliminaries out of the way, we proceed to I/O. The way q handles I/O is Spartan. No instantiation of readers, writers, serializers and the like. We admit that the notation is funky, but you will grow to appreciate its conciseness just as a serious driver prefers a manual transmission.
File I/O begins with symbolic handles. A ‘’symbolic file handle’’ is a symbol of a particular form that represents the name of a resource on the file system. The leading ‘:’ distinguishes the symbol as a handle. For example,
We use the following simple table in our demonstration.
q)t:( c1:`a`b`c; c2:1.1 2.2 3.3) q)t _
Pick a destination to write your files. Because this tutorial is being, the examples here will use ,
You should replace this with your chosen directory in what follows.
To save the table t in a serialized binary data file, use the built-in function (‘’’set’’’) with symbolic file handle as left operand and the source data as the right operand.
q)`:/q4m/examples/t set t `:/q4m/examples/t
Observe that the console echoes the symbolic file handle in case of success. To read the stored data and deserialize it back into the session, use (get) with the symbolic file handle.
q)get `:/q4m/examples/t _
Presto! It’s out and back.
To write text data to a file we use one of the overloads of the infelicitously named (0:) operator. The key idea is that q considers a text file to correspond to a list of strings, one string per file record. We supply (0:) with a symbolic file handle as its left operand and a list of strings (i.e., a list of lists of char) in the right operand.
q)`:/q4m/life.txt 0: ("Meaning";"of";"life") _
To read a text file as a list of strings, use (read0) with the symbolic handle.
q)read0 `:/q4m/examples/life.txt _
And now, what everyone is waiting for: writing and reading csv files. Hold on to your hats, as this uses three different overloads of (0:). One to prepare the tables as text; the one we already met to write text files; and one to read formatted text files. Certainly a regrettable naming convention.
Preparing a table as csv text is simple; q handles the quoting and escaping of special characters. Apply (0:) with the defined constant csv as left operand and the table in the right operand.
q)csv 0: t _
Your console display shows the table properly prepared as strings. Now compose this result with the previous overload of (0:) and write it out. As a check, we use (read0) to read back the text file.
q)`:/q4m/examples/t.csv 0: csv 0: t _ q)read0 `:/q4m/examples/t.csv _
Finally, we demonstrate the third overload of (0:) to parse the formatted csv file into the q session as a table. The right operand is a symbolic file handle. The left operand is a control list with two items. The first is a string of upper case characters indicating the types of each field within the text row.
The second item of the control list is the field separation character—in our case this is ‘,’. This separator char should be enlisted if there are column headers in the first row of the file, as in our case. These headers are used as table column names. For our example we have,
q)("SF"; enlist ",") 0: `:/q4m/examples/t.csv _
Here "S" and "F" indicate that there are two fields, having types symbol and float. The separator is an enlisted ‘,’.
Yes, the naming and notation is obscure. But you have to admit that file I/O can’t get much simpler.
Reprinted with the author's permission from: q for Mortals Version 3, An Introduction to Q Programming by Jeffry A. Borror.
©2015 Jeffry A. Borror/ q4m LLC