Kelmscott/docs

Kelmscott

Fixed-width records in, typed values out. Nothing in between.

Kelmscott reads and writes the fixed-width record files that instrument loggers, meter concentrators and older accounting systems still produce by the gigabyte. It does one job: turn a byte stream into typed records and back again, without guessing.

Design

Three decisions shape the whole library, and everything else follows from them.

At a glance

layout := kelmscott.Layout{
    {Name: "id",      Width: 8,  Type: kelmscott.Integer},
    {Name: "station", Width: 12, Type: kelmscott.Text},
    {Name: "taken",   Width: 14, Type: kelmscott.Timestamp, Format: "20060102150405"},
    {Name: "reading", Width: 10, Type: kelmscott.Decimal, Scale: 3},
}

r := kelmscott.NewReader(f, layout)
for r.Next() {
    rec := r.Record()
    // rec.Int("id"), rec.Text("station"), rec.Decimal("reading")
}
if err := r.Err(); err != nil {
    return err
}
The reader never silently coerces. A field declared Integer that contains spaces is an error, not a zero — because a zero reading and a missing reading mean different things to whoever audits the archive four years from now.

Compatibility

EncodingsASCII, latin-1 and UTF-8; declared per layout, never sniffed
Line endingsLF, CRLF, or fixed-length records with no terminator at all
Numeric formatsZoned decimal, packed decimal, plain ASCII with implied scale
PaddingLeft or right, space or zero, per field
StabilityThe layout and reader APIs have not changed since 2.0

What it is not

Kelmscott is not a CSV library, not a schema registry and not an ETL framework. It has no plugin system and no configuration file. If your records are delimited rather than fixed-width, the standard library already does the job better than this would.

Where to go next

The guide walks through a complete read and write cycle, including the three mistakes that account for most of the questions we get. The reference lists every type, every option and every error condition.