Read all fields from a .sav file.All fields include the full Schema and all data cells as a Row[]
Still in development:TODO: expose objects of Column classesTODO: concatenate long string column valuesTODO: uncompressed data filesTODO: unrecognized codes
From a node.js Buffer usingfs.readFile
fs = require('fs');let all;const parser = new SavParser();// with async readFilefs.readFile('some/path/to/file.sav', (err, data) => { parser.all(new Feeder(data.buffer)).then( result => all = result )});// with syncronous `readFileSync`parser.all( new Feeder(fs.readFileSync('/some/path/to/file.sav').buffer)).then( parsed => all = parsed);// nodejs Buffers may need to be sliced when accessing the underlying ArrayBuffer// It's always safer to slice from the byteOffset (which commonly is 0) and byteLengthnew Feeder( buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));
In the browser with File API
<input type="file" onchange = "onChange"></input>
const all;function onChange(event){ const file = event.target.files[0]; const reader = new FileReader(); const parser = new SavParser(); reader.onload = function(data){ data.arrayBuffer().then( buffer => parser.all(new Feeder(buffer)) ).then( parsed => all = parsed ); } reader.readAsArrayBuffer(file);}
Parsing less than the complete data file
const parser = new SavParser();// read only the meta fields from a sav fileparser.meta(new Feeder(buffer)).then(parsed => {/* do stuff */});// read only the header fields from a sav file// Header here refers to the head of the columns of the data, i.e.// properties of the columns in the data fileparser.headers(new Feeder(buffer)).then(parsed => {/* do stuff */});// read all schema fields from a sav file// Schema here refers to all information except for the data cells themselvesparser.schema(new Feeder(buffer)).then(parsed => {/* do stuff */});
DataSet interface for parsed dataSavvy class implements DataSet
const parser = new SavParser();let dataset;parser.all(new Feeder(buffer)).then( parsed => dataset = new Savvy(parsed))// n : number - number of casesdataset.n// names : Array<string> - column names (short unique names)dataset.names// labels : Map<string, string> - column long labels (key-value by unique name)dataset.labels// row(index : number) : Map<string, number | string> - get a row as key-value mapdataset.row(0)// col(key : string) : Array<number> | Array<string> - get a column as an arraydataset.col('IDField')// view(indices? : Array<number>, keys? : Array<string>) : DataSet - subset by rows/columns
See types.d.ts file for how parsed data is encoded