As you know, lately I've been publishing simple Cordova examples that involve the file system. I'm working on a demo that involves background asset downloads (see the blog entry) but I thought I'd take a break from that and write up something super simple, but hopefully helpful, that demonstrates file writing.

With that in mind I built a demo that writes to a log file. The idea being that your app may want to record what it is doing. Normally you would do that via XHR to a server, but logging to a file ensures it will work offline as well. And perhaps you don't really need the data on your server but just want a log you can check later if things go wrong. Let's take a look at the code bit by bit.

The first thing I need to do is get a handle to the file. I'm going to use a file inside cordova.file.dataDirectory, which is an alias to an application-specific folder with read/write access.

	window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function(dir) {
		console.log("got main dir",dir);
		dir.getFile("log.txt", {create:true}, function(file) {
			console.log("got the file", file);
			logOb = file;
			writeLog("App started");			
		});
	});

resolveLocalFileSystemURL converts the alias path into a directory entry object. That has a variety of methods but the one we care about is getFile. Note the create:true flag. This ensures that the file will be created the first time it is run. I also copy the file object into a variable logOb that is global to my application. Finally I call writeLog. That's my utility function. Let's look at that next.

function writeLog(str) {
	if(!logOb) return;
	var log = str + " [" + (new Date()) + "]\n";
	console.log("going to log "+log);
	logOb.createWriter(function(fileWriter) {
		
		fileWriter.seek(fileWriter.length);
		
		var blob = new Blob([log], {type:'text/plain'});
		fileWriter.write(blob);
		console.log("ok, in theory i worked");
	}, fail);
}

So first off, if logOb wasn't created, we simply return. My thinking here is that log file writing is not required for the application. I want to silently ignore if we couldn't write to the file system for whatever reason. I modify the input a bit (adding a timestamp and a newline) and then begin the write operation. This particular code was taken right from the HTML5Rocks article on the FileSystem API. It uses seek to append as opposed to overwrite the file.

With this in place I could then add calls to the log utility from my application. Since my "application" is just a demo, I added two buttons that do nothing but log.

	document.querySelector("#actionOne").addEventListener("touchend", function(e) {
		//Ok, normal stuff for actionOne here
		//
		//Now log it
		writeLog("actionOne fired");
	}, false);

	document.querySelector("#actionTwo").addEventListener("touchend", function(e) {
		//Ok, normal stuff for actionTwo here
		//
		//Now log it
		writeLog("actionTwo fired");
	}, false);

The final thing I did was add a special function that would read the file out and send it to console. I did this just for testing.

function justForTesting() {
	logOb.file(function(file) {
		var reader = new FileReader();

		reader.onloadend = function(e) {
			console.log(this.result);
		};

		reader.readAsText(file);
	}, fail);

}

To see this in action, I used GapDebug and my iOS simulator. That let me run justForTesting right from my browser. In the screen shot below, note that the beginning of the file isn't formatted right. That's because I forgot the newline initially.

I hope this helps. You can find the complete source in my GitHub repo with the rest of my demos: https://github.com/cfjedimaster/Cordova-Examples/tree/master/writelog