function readFile(path, options, callback) {
        var encoding = options.encoding || "utf8";

        // callback to be executed when the call to stat completes
        //  or immediately if a stat object was passed as an argument
        function doReadFile(stat) {
            if (stat.size > (FileUtils.MAX_FILE_SIZE)) {
                callback(FileSystemError.EXCEEDS_MAX_FILE_SIZE);
            } else {
                appshell.fs.readFile(path, encoding, function (_err, _data, encoding, preserveBOM) {
                    if (_err) {
                        callback(_mapError(_err));
                    } else {
                        callback(null, _data, encoding, preserveBOM, stat);
                    }
                });
            }
        }

        if (options.stat) {
            doReadFile(options.stat);
        } else {
            exports.stat(path, function (_err, _stat) {
                if (_err) {
                    callback(_err);
                } else {
                    doReadFile(_stat);
                }
            });
        }
    }
Read the contents of the file at the given path, calling back
asynchronously with either a FileSystemError string, or with the data and
the FileSystemStats object associated with the read file. The options
parameter can be used to specify an encoding (default "utf8"), and also
a cached stats object that the implementation is free to use in order
to avoid an additional stat call.

Note: if either the read or the stat call fails then neither the read data
nor stat will be passed back, and the call should be considered to have failed.
If both calls fail, the error from the read call is passed back.

@param {string} path
@param {{encoding: string=, stat: FileSystemStats=}} options
@param {function(?string, string=, FileSystemStats=)} callback