Examples
Introduction
Initialize FSO using
/**
*	FSO(
*		opt_byteSize, [= 1024 * 1024 * 1024]
*		opt_usePersistentStorage, [= false]
*		opt_successCallback, [= null]
*		opt_errorCallback [= null]
* 	);
*/

var fso = new FSO(1024 * 1024 * 100, false);
We've now created a 100MB temporary storage sandboxed filesystem! This executes asynchronously. All queues created (and executed) before initialization is complete will be halted until the FSO instance is ready. This means the successCallback is *not needed* to execute file I/O, but it is recommended. But what is a queue?
Queues
A queue (FSOQueue) is a set of instructions to be executed on the file system sequentially. While using FSO.js, all file I/O operations are done using queues. These queues can have any number of commands, and separate queues are run independent of one another (so be careful, depending on what files you're manipulating). Queues have access to the following commands (methods):
write
append
insert
put

mkdir

rm
rmdir

rename
move
copy

read
readBuffer

info
list

getBytes
	
Writing a text file
Let's write to
hello.txt
in our root directory.
The first step is to create a queue.
var fsq = fso.createQueue();
That's it! Our queue is ready. We can now prepare to write to a file.
fsq.write(
	'hello.txt',
	'Hello World',
	function() { console.log('wrote to file');
})
The three parameters passed here, in order, are filename (including path, all paths are based from root directory), contents, and an *optional callback* that will run when the write has completed. All queued commands can take an optional callback parameter as their last argument. However, we're not done. The queue is still in a
READY
state, accepting more commands. We're finished with it now and want to actually perform our action...
fsq.execute(
	function() { console.log('Complete!') },
	function(e) { console.log('OMG an error!'); }
);
You'll notice the first function passed to
.execute()
, this is a success callback that will fire upon completion of the queue. Optionally, a second error callback can be provided that will override default error reporting if any command in the queue fails.
If everything goes as planned (and it should), you should see the following in your console:
> wrote to file
> Complete!
Appending to a file
So, we've created
hello.txt
, let's add something to it and read it.
fso
	.createQueue()
		.append(
			'hello.txt',
			' ... from Canada, eh ;)',
			function() { console.log('Appended!'); }
		)
		.read(
			'hello.txt',
			function(data) { console.log(data); }
		)
	.execute(function() { console.log('donezo!'); });
In order to save some keystrokes, we've chained our methods together. Every command will return the same instance of your queue, allowing you to do this once your queue has been created. We've also brought in
.read()
to read a file for us.
You might expect your output to be...
> Appended!
> Hello World ... from Canada, eh ;)
> donezo
However, there's no guarantee that our two queues will execute in order. We may end up with:
> Appended!
> ... from Canada, eh ;)
> donezo!
Logged first. Separate queues are run asynchronously, and there is no guarantee on the order in which they will proceed. If your file I/O is dependent upon sequential processing, combine all statements in a single queue. Our
write()
+
append()
now becomes:
fso
	.createQueue()
		.write(
			'hello.txt',
			'Hello World',
			function() { console.log('wrote to file'); }
		)
		.append(
			'hello.txt',
			' ... from Canada, eh ;)',
			function() { console.log('Appended!'); }
		)
		.read(
			'hello.txt',
			function(data) { console.log(data); }
		)
	.execute(function() { console.log('donezo!'); });
with an output of
> wrote to file
> Appended!
> Hello World ... from Canada, eh ;)
> donezo!
Inserting into a file
The final way to add contents to a file is to
insert()
fso
	.createQueue()
		.insert(
			'inserted_file.txt',
			'!',
			10,
			function() { console.log('Inserted'); }
		)
		.read(
			'inserted_file.txt',
			function(data) {
				console.log(data);
				console.log(data.length)
			}
		)
	.execute(function() { console.log('done'); });
The output of this queue will be:
> Inserted
> !
> 11
> done
You'll see the data string as "!" in the console, though the length is given as 11 characters. This is because you've inserted "!" at position 10, and FSO has zeroed out the file length preceding this value. The string is indeed 11 characters, each with a byte value of (binary)
00000000
. These null characters do not show up in the console.
Writing files non-sequentially
You may want to write a file non-sequentially. In order to do this, you must first know the total length of the file. You can create a completely empty file by using:
fso
	.createQueue()
		.insert('empty.file', '', 1024 * 1024)
	.execute();
Once this queue has complete,
empty.file
will be a 1MB (1024 * 1024 Byte) file in your root directory.
As long as the file exists (make sure a provided callback has completed), you can now write any position in the file using:
fso
	.createQueue()
		.insert('empty.file', data, byteOffset)
	.execute()
Where
data
is your data to be written, and
byteOffset
is the write position, in bytes.
While
.insert()
will always zero out a file between its current length and
byteOffset
, there is no guarantee that your data will be written as expected if you're trying to write to multiple parts of the file simultaneously if the file has to be extended dynamically (zeroed) during the write.
Grabbing a file from the user
Let's say you have a file input, and you'd like the user to put some files in your FileSystem sandbox.
<input type="file" multiple id="file-select">
FSO.js allows you to do this very easily.
var fso = new FSO(1024 * 1024 * 1024, false);
var fsu = FSOUtil;

document
	.getElementById('file-select')
	.addEventListener('change', function(e) {
	
		var fsq = fso.createQueue();
	
		var files = this.files;
		for(var i = 0, len = files.length; i < len; i++) {
			fsq.put(files[i], '/');
		}
		
		fsq.list(
			'/',
			0,
			function(list) {
				console.log(fsu.prettyDirectory(list));
			}
		);
		fsq.execute();
		
	});
Assuming user has chosen
myFile.txt
,
myImage.jpg
and
myVideo.avi
, you should see:
[/]
  - myFile.txt (10B)
  - myImage.jpg (86.2kB)
  - myVideo.avi (140.86MB)
Accessing stored file resources
Any file resource can be accessed (as
src
attribute of an element, for example) by using
FSO.toURL(path)
For example, if a file
/images/spritesheet.png
exists in your File System, you can create a new image of it and append it to the document using:
// assume fso is your instance of FSO...

var img = new Image();
img.src = fso.toURL('images/spritesheet.png');
document.body.appendChild(img);
Navigating the file system
The FSOQueue object has a number of useful functions for navigating the file system, you can read about them in the documentation, but here's a brief example.
var fsu = FSOUtil;

fso
	.createQueue()
		// recursively remove root directory, empties it
		.rmdir('/')
		.write('file', 'FILE!')
		// creates 'test' directory in root
		.mkdir('test')
		// creates 'test/inside'
		.mkdir('test/inside')
		// recursively creates 'test2/inside'
		.mkdir('test2/inside2')
		.write('test2/def.txt', 'def')
		.write('test2/inside2/abc.txt', 'abc')
		// remove 'abc.txt'
		.rm('test2/inside2/abc.txt')
		// remove *empty* directory 'inside'
		.rm('test2/inside')
		// recursively remove *non-empty* directory 'test2'
		.rmdir('test2')
		// copy and rename
		.copy('test', '/', 'test3')
		// rename
		.rename('test3/inside', 'renamed')
		// move
		.move('test3/renamed', '/')
		// print out current directory structure
		.list(
			'/',
			null,
			function(list) {
				console.log(fsu.prettyDirectory(list));
			}
		)
	.execute();
This beast of a test queue will run and log the directory/file structure of the root directory ('/'), which should be:
[/]
  - file (5B)
  [test]
  	[inside]
  [test3]
  [renamed]