3

I read on Cordova's documentation for android platform a code snipped and tried to use it for writing a JS object on a text file. The object gets successfully written but when I read it with FileReader API I can't get output as expected.

function writeFile(fileEntry, dataObj, isAppend) {
    // Create a FileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function (fileWriter) {

        fileWriter.onwriteend = function() {
            console.log("Successful file read...");
            readFile(fileEntry);
        };

        fileWriter.onerror = function (e) {
            console.log("Failed file read: " + e.toString());
        };

        // If we are appending data to file, go to the end of the file.
        if (isAppend) {
            try {
                fileWriter.seek(fileWriter.length);
            }
            catch (e) {
                console.log("file doesn't exist!");
            }
        }
        fileWriter.write(dataObj);
    });
}

function readFile(fileEntry) {

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

        reader.onloadend = function() {
            console.log("Successful file read: " + this.result);

            //displayFileData(fileEntry.fullPath + ": " + this.result);
        };
        reader.onload = function(){
            k=reader.readAsText(file);

        };
       reader.readAsText(file);

    },onErrorLoadFs );
}

Format of object I want to read :

function sub(name,absent,present){
    this.name=name;
    this.absent=absent;
    this.present=present;

}

var S = new sub('Physics',1,3);
var k= new sub();

What exactly I want to do :

I am writing an object S on the file which appears like this when opened

{"name":"Physics","absent":1, "present" : 3}

Now after reading the file (which in my case is filetoAppend.txt) I want to assign these values to another object k so that when I run k.name, Physics is shown as output.

console output

k
"{"name":"Physics","absent":1,"present":3}"
k.name
undefined
pandafy
  • 184
  • 13

1 Answers1

2

With the Cordova File Plugin, there are two essential pieces of information to remember:

1.Like all Cordova plugins, you have to wait for the deviceready event before you try anything,

2.Then, Use window.resolveLocalFileSystemURL(<path>, <successHandler>, <errorHandler>)

window.resolveLocalFileSystemURL() returns a FileEntry or DirectoryEntry instance (depending on whether you gave a file or a directory as path as its first parameter), which you can then work with.

WRITING TO A FILE

document.addEventListener('deviceready', onDeviceReady, false);  
function onDeviceReady() {  
    function writeToFile(fileName, data) {
        data = JSON.stringify(data, null, '\t');
        window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (directoryEntry) {
            directoryEntry.getFile(fileName, { create: true }, function (fileEntry) {
                fileEntry.createWriter(function (fileWriter) {
                    fileWriter.onwriteend = function (e) {
                        // for real-world usage, you might consider passing a success callback
                        console.log('Write of file "' + fileName + '"" completed.');
                    };

                    fileWriter.onerror = function (e) {
                        // you could hook this up with our global error handler, or pass in an error callback
                        console.log('Write failed: ' + e.toString());
                    };

                    var blob = new Blob([data], { type: 'text/plain' });
                    fileWriter.write(blob);
                }, errorHandler.bind(null, fileName));
            }, errorHandler.bind(null, fileName));
        }, errorHandler.bind(null, fileName));
    }

    writeToFile('example.json', { foo: 'bar' });
}

WRITING FROM FILE

document.addEventListener('deviceready', onDeviceReady, false);  
function onDeviceReady() {  
    function readFromFile(fileName, cb) {
        var pathToFile = cordova.file.dataDirectory + fileName;
        window.resolveLocalFileSystemURL(pathToFile, function (fileEntry) {
            fileEntry.file(function (file) {
                var reader = new FileReader();

                reader.onloadend = function (e) {
                    cb(JSON.parse(this.result));
                };

                reader.readAsText(file);
            }, errorHandler.bind(null, fileName));
        }, errorHandler.bind(null, fileName));
    }

    var fileData;
    readFromFile('data.json', function (data) {
        fileData = data;
    });
}

cb is the callback function that you need to pass when calling this function

For full reference use:https://www.neontribe.co.uk/cordova-file-plugin-examples/

Updated based on your updated Question

In reader.onloadend you can get the result of the file and assign to your output object k or can call callback function incase.

reader.onloadend = function (e) {
   //cb(JSON.parse(this.result));
   var k=JSON.parse(this.result);
   console.log(k.name + ", " + k.absent+ ", " + k.present);
  };

var k = JSON.parse('{"name":"Physics","absent":1, "present" : 3}');
console.log(k.name + ", " + k.absent + ", " + k.present);
NullPointer
  • 7,094
  • 5
  • 27
  • 41
  • What is cb in `cb(JSON.parse(this.result));`? – pandafy Jul 04 '18 at 09:10
  • @GaganRajput -It is a callback function that you need to pass when calling this function – NullPointer Jul 04 '18 at 09:34
  • I don't see it defined anywhere. – pandafy Jul 04 '18 at 09:48
  • Buddy as it is async process so you need to pass a call back function when you calling readFromFile method. Pass the reference of a JavaScript method that will handle the result – NullPointer Jul 04 '18 at 09:59
  • I have edited my question. Also consider reading example given in documentation of cordova-plugin-file whose link is also included in the question. – pandafy Jul 04 '18 at 10:13
  • I understand your problem. So in callback you can get JSON data of file and can set in object **k**. **callback function is just a function that u want to execute from another function** For callback understanding u can refer https://www.w3schools.com/jquery/jquery_callback.asp – NullPointer Jul 04 '18 at 10:22
  • Is it possible to do what I'm trying to do. If so can you help me with the respective code. I am new to JS and Cordova but I have studied data file handling in C++ in school. – pandafy Jul 04 '18 at 10:33
  • @GaganRajput Hi I seached a lot for you and find the best example for you: https://www.tutorialspoint.com/cordova/cordova_file_system.htm This link have very clear steps you have to do and also have the javascript callback function. Do not forget to upvote and accept the answer if found useful.Thanks – NullPointer Jul 04 '18 at 14:45
  • Thank you for devoting your time and helping me but, I already know that and things which are described on that page can be done on my code too. The main problem is I can't feed data into objects of my code. – pandafy Jul 04 '18 at 14:58
  • ok tell me from where you are calling **readFile(fileEntry)** function and also tell me in your code are you getting data in **k** using console log or alert? – NullPointer Jul 04 '18 at 15:00
  • since I already written an object to a file `JSON.parse(this.result)` return some error like `unexpected token o` – pandafy Jul 04 '18 at 15:27
  • https://stackoverflow.com/questions/44038201/save-json-data-to-text-file-and-read-it – NullPointer Jul 04 '18 at 15:30
  • Hi @NullPointer would you mind take at look at this? https://stackoverflow.com/questions/67565787/promisify-filereader-onload-got-typeerror-cannot-read-property-then-of-undefi My initial thought was to wrap the whole thing in a promise so that it will do the next after the reading is finished, but after reading your post makes me wonder adding a callback works too. But i dont know how. – Sam Min Wong May 17 '21 at 19:55
  • It seems like the author thinks supporting promise is not a good idea: https://github.com/apache/cordova-plugin-file/issues/344. Also I try to use your code but ` directoryEntry.getFile` raised `Unresolved function or method getFile()` and `fileEntry.file` raised `Unresolved function or method file()` Been scratching my heads for the last few days. Any help will be much much appreciated. – Sam Min Wong May 17 '21 at 20:02