02-10-2018 01:02
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-10-2018 01:02
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
I wanted to ask how I am able to replace values in JSON files, without overriding the whole file and losing the rest of the property values. Because if I do it in the following way:
json_color.hours = element.data.value; fs.writeFileSync("colors.txt", json_color, "json");
I am always replacing the previous file and I only want to change one property value and keep the other remaining property values.
Answered! Go to the Best Answer.
Accepted Solutions
02-10-2018 02:26
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post


02-10-2018 02:26
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
I would write the file only on app unload, and also use CBOR format for speed purposes.
import { me } from "appbit";
me.onunload = () => { fs.writeFileSync("colors.txt", json_color, "cbor"); }
02-10-2018 02:26
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post


02-10-2018 02:26
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
I would write the file only on app unload, and also use CBOR format for speed purposes.
import { me } from "appbit";
me.onunload = () => { fs.writeFileSync("colors.txt", json_color, "cbor"); }
02-10-2018 06:07
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-10-2018 06:07
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
For settings, which your example appears to be, then @JonFitbit response is certainly the best solution.
If you were collecting data, for example sensor data for later use, then take a look at writeSync, which is for binary file use. It does add a level of complexity, but also opens up reading or updating particular 'records' at will. Each record will be a fixed byte length. I was 'playing about' with writeSync yesterday and have working code if this route is of interest/use (read/write/update) @Senorts.
02-10-2018 06:54
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-10-2018 06:54
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Thank's very much for the help.

02-10-2018 08:00 - edited 02-10-2018 08:03
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-10-2018 08:00 - edited 02-10-2018 08:03
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
As per your message @Senorts, here you are. Please remember this is test code to confirm functionality and usage of writeSync.
import * as fs from "fs"; let fh = 0; let fileName="filename.bin"; // setup variables for updating the record var sentBuffer = new ArrayBuffer(1); var sentFlag = new Uint8Array ( sentBuffer, 0, 1 ); // 1 x 1 bytes sentFlag[0] = 1; //setup variables for the record format let recSize = 58; var buffer = new ArrayBuffer(recSize); var dtMillies = new Uint32Array ( buffer, 0, 2 ); // 2 x 4 bytes var gpsLat = new Float64Array( buffer, 8, 1 ); // 1 x 8 bytes var gpsLon = new Float64Array( buffer, 16, 1 ); // 1 x 8 bytes var gpsSpeed = new Float64Array( buffer, 24, 1 ); // 1 x 8 bytes var gpsAccuracy = new Float64Array( buffer, 32, 1 ); // 1 x 8 bytes var gpsHeading = new Uint16Array ( buffer, 40, 1 ); // 1 x 2 bytes var heartRate = new Uint16Array ( buffer, 42, 1 ); // 1 x 2 bytes var steps = new Uint16Array ( buffer, 44, 1 ); // 1 x 2 bytes var altitude = new Uint16Array ( buffer, 46, 1 ); // 1 x 2 bytes var ascent = new Uint16Array ( buffer, 48, 1 ); // 1 x 2 bytes var descent = new Uint16Array ( buffer, 50, 1 ); // 1 x 2 bytes var reading = new Uint32Array ( buffer, 52, 1 ); // 1 x 4 bytes var battery = new Uint8Array ( buffer, 56, 1 ); // 1 x 1 bytes var sent = new Uint8Array ( buffer, 57, 1 ); // 1 x 1 bytes let myDate=Date.now() let recCount=0; let firstUnsent = 0; writeRecord(); writeRecord(); showFileDetails(); firstUnsent = findFirstUnsent(); if (firstUnsent>0) { updateRecordAsSent(firstUnsent); } showRecordsToConsole(); function writeRecord() { fh = fs.openSync(fileName, 'a+'); dtMillies[0] = parseInt(myDate/100000000); dtMillies[1] = myDate%100000000; gpsLat[0] = 179.987654321 gpsLon[0] = -179.123456789 gpsHeading[0] = Math.floor(Math.random() * 360); gpsSpeed[0] = 2.123456791 heartRate[0] = 120 + Math.floor(Math.random() * 80); gpsAccuracy[0] = 21.2134254723 steps[0] = Math.floor(Math.random() * 3); altitude[0] = 10 + Math.floor(Math.random() * 1991); ascent[0] = 4 descent[0] = 0 battery[0] = 78 reading[0] = 1 sent[0] = 0 fs.writeSync(fh, buffer); // write the record fs.closeSync(fh); // and commit changes -- important if you are about to read from the file } function showFileDetails() { let stats = fs.statSync(fileName); if (stats) { recCount=stats.size/recSize; console.log("File size: " + stats.size + " bytes"); console.log("Number of Records: " + recCount); console.log("Last modified: " + stats.mtime); } } function getNumberOfRecords() { recCount=0; let stats = fs.statSync(fileName); if (stats) { recCount=stats.size/recSize; } return recCount; } function findFirstUnsent() { let retVal=0; fh = fs.openSync(fileName, 'a+'); for (let i = 0; i < recCount; i++) { fs.readSync(fh, buffer, 0, recSize, i*recSize ); if ((sent[0]==0) && (retVal===0)) { retVal=i+1; i=recCount; } } fs.closeSync(fh); return retVal; } function updateRecordAsSent(recordID) { fh = fs.openSync(fileName, 'a+'); fs.writeSync(fh,sentBuffer,0,1,(recSize*recordID)-1); fs.closeSync(fh); } function showRecordsToConsole() { recCount=getNumberOfRecords(); fh = fs.openSync(fileName, 'r+'); for (let i = 0; i < recCount; i++) { fs.readSync(fh, buffer, 0, recSize, i*recSize ); console.log("Record: "+(i+1)+" Millies:"+(dtMillies[0]*100000000+dtMillies[1])+" Lat:"+gpsLat[0]+" Lon:"+gpsLon[0]+" Heading:"+gpsHeading[0]+" Speed:"+gpsSpeed[0]+" HR:"+heartRate[0]+" Accuracy:"+gpsAccuracy[0]+" Steps:"+steps[0]+" Alt:"+altitude[0]+" Asc:"+ascent[0]+" Des:"+descent[0]+" Bat:"+battery[0]+" Reading:"+reading[0]+" Sent:"+sent[0]); } fs.closeSync(fh); } function packString(mystring) { let i=0; while (mystring.length<16) { mystring+=' '; } for (i = 0; i < mystring.length; i++) { usernameView[i]=mystring.charCodeAt(i); } } function unPackString(usernameView) { let retVal=''; let i=0; for (i = 0; i < usernameView.length; i++) { retVal+=String.fromCharCode(usernameView[i]); } return retVal }
05-15-2020 22:28
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

05-15-2020 22:28
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
one really interesting thing i found in using @SunsetRunner's code it looks like the Uint*Arrays need to be in a certain order to pack them into the ArrayBuffer as tightly as possible. for example, i have two Uint*Arrays i'm passing to the buffer. if i put the Uint32Array first, i can get the record size down to 9 bytes. but if the Uint8Array is first, the record size has to be 16 bytes (almost twice as large). otherwise, i get an error. anyone know the logic behind this in the Fitbit SDK? does this have something to do with Endianness? Here's my code sample:
allows for a record size of 9 bytes:
var buffer = new ArrayBuffer(recSize);
var attention = new Uint8Array(buffer, 8, 1);
var dtMillies = new Uint32Array(buffer, 0, 2);
var buffer = new ArrayBuffer(recSize);
var attention = new Uint8Array(buffer, 0, 1);
var dtMillies = new Uint32Array(buffer, 8, 2);

