Component Files

>> << Ndx Usr Pri Phr Dic Rel Voc !: wd Help User

# Component Files (jfiles)

Jfiles are component `files` for J data. A jfile can be thought of as a boxed list which is stored on file. An element of the boxed list is referred to as a component, and can store a noun of any type, shape or size. File components are numbered sequentially from 0 upwards.

To access the system (assuming you are using the standard profile):

       load 'jfiles'

This populates a locale `jfiles` with utility functions, and defines the following verbs in the `z` locale:

       jcreate
       jerase
       jappend
       jread
       jreplace
       jdup
       jsize

You create a file using `jcreate`.

`jappend` adds new items to the file. Each item added to the file is stored in a new component. Several items can be added to the file at a time.

`jread` reads items from file, and `jreplace` replaces items on file.

`jdup` duplicates a file, and `jsize` returns its size.

You can refer to a file either by its file name, or by its file handle. The default file extension is .ijf - this is used if no file extension is given.

You cannot delete components once created. If you need to reclaim space no longer required, either replace the components with empties, or else duplicate the file, copying only the components required.

Create file
jcreate
create a file. The right argument is the filename. Any existing file is overwritten. The result is 1 if successful, else 0. For example:

       jcreate 'mydata'
    1

Note that since the file extension was not specified, this actually creates a file named mydata.ijf.

Read and write file
jappend
append to file. The left argument is a boxed list, with each item in the list stored in a new file component. An open noun is treated as a single boxed item. The right argument is the filename. The result is the new component numbers created. For example:

       'header' jappend 'mydata'
    0

       ('rec1';'rec2') jappend 'mydata'
    1 2

       (< <\1 2 3) jappend 'mydata'
    3

       (2 2$10 20 30 40) jappend 'mydata'
    4

jread
read file. The right argument is the filename, linked with one or more component numbers. The result has the same shape as the component numbers. For example:

       > jread 'mydata';4
    10 20
    30 40

       jread 'mydata';i.5
    +------+----+----+-------------+-----+
    |header|rec1|rec2|+-+---+-----+|10 20|
    |      |    |    ||1|1 2|1 2 3||30 40|
    |      |    |    |+-+---+-----+|     |
    +------+----+----+-------------+-----+

       jread 'mydata';i.2 2
    +------+-------------+
    |header|rec1         |
    +------+-------------+
    |rec2  |+-+---+-----+|
    |      ||1|1 2|1 2 3||
    |      |+-+---+-----+|
    +------+-------------+

jreplace
replace in file. The result is the components replaced. For example:

       (1000;'abcde') jreplace 'mydata';1 2
    1 2

       jread 'mydata';i.3
    +------+----+-----+
    |header|1000|abcde|
    +------+----+-----+

The left argument is reshaped if necessary to match the components in the right argument. For example, the following replaces components 1-3, each with the word `'reserved'`:

       'reserved' jreplace 'mydata';1 2 3
    1 2 3

Utilities
jdup
duplicate file. The left argument is the new filename; if elided, the file is duplicated in place. The right argument is the source filename, optionally linked with one or more component numbers to be copied to the new file, in the order given. By default, the entire file is duplicated. The result is the number of components written. For example:

       'newdata' jdup 'mydata'
    5

       'newdata' jdup 'mydata';2 0 1
    3

jsize
size of file, as 4 numbers:

starting component number (0)
number of components
length of file in bytes (same as result of `1!:4`)
amount of free space that could be recovered by duplicating the file

For example:

       jsize 'newdata'
    0 5 1312 0

jerase
erase file, for example:

       jerase 'newdata'
    1

File handles
You can refer to a file either by its filename, or by its file handle if you have already opened the file. For most purposes we recommend using the filename. However, if you have a great deal of file activity, you may find it faster to open the file first, then use the file handle; this means the system does not have to open and close the file each time it is accessed. The utilities `jopen` and `jclose` in the jfiles locale can be used for this purpose. For example:

       h=. jopen_files_ 'mydata'

... process file using handle `h...`

       jclose_files_ h
    1

File structure
Each file is structured as a header record, followed by data. The header record is as follows:

[0] version
[1] starting component
[2] number of components
[3] file length
[4] directory pointer
[5] freelist pointer
[6] sequence number

Freelist
Each component is stored in its 3!:1 representation in a space that is a power of 2. This means that on average, the representation fills 75% of the space allocated, and allows some space for growing replaces. If the space required on replacement is less than half the space allocated, then the balance is freed up.

If you replace a component with a noun of smaller size, then this may result in some unused space. The system keeps track of this in the freelist, and attempts to reuse it where possible. The total free space available is given in the fourth element of the result of `jsize`, and this is the space that would be freed by duplicating the file using `jdup`.

>> << Ndx Usr Pri Phr Dic Rel Voc !: wd Help User