简体   繁体   English

如何在 Cordova 中读取/写入本地 json 或文本?

[英]How can I read / write a local json or text in Cordova?

I'm trying to read a JSON file inside the www with Cordova.我正在尝试使用 Cordova 读取 www 中的 JSON 文件。

I'm trying with a lot of systems, tests and solutions which, however, are failing one after the other.我正在尝试许多系统、测试和解决方案,但是,它们一个接一个地失败了。

The simplest concept (fetch)最简单的概念(fetch)

Result: locally work.结果:本地工作。 On app: "fetch fail" if use cordova.file.dataDirectory .在应用程序上:如果使用cordova.file.dataDirectory则“获取失败”。 The result is: "NetworkError when attempting to fetch resource".结果是:“尝试获取资源时出现网络错误”。

document.addEventListener('click', test ,true);
document.addEventListener('touchstart', test ,true);

function test(){

  alert("try fetch");

  const jsonFile = "./geoita.json"; // fail on app
  const jsonFile = cordova.file.dataDirectory+"geoita.json"; //security

  var headers = new Headers({
      "Content-Type": "text/plain",
      "Accept": "text/plain"
   });
  window.fetch( jsonFile, headers )
  .then( resp => resp.json() )
  .then( json => {

    console.log(json);
    alert("Result: "+json);
    document.body.innerHTML=JSON.stringify(json);


  })
  .catch(function(error) {
    console.log('ERROR: ' + error.message);
    alert('ERROR: ' + error.message);
  });

 };

TEST 2 (request)测试 2(请求)

Result: security on file.结果:文件安全。 You can't get file, so you can't read it.您无法获取文件,因此无法读取它。

  var req = new XMLHttpRequest();
  req.onreadystatechange = () =>
  {
    console.log("try in api style...");
    if (req.readyState==4 && req.status==200)
    {
        console.log("reading...");
        let json = JSON.parse(req.responseText);  
        console.log(json);
    }
    else {
      console.log("try in api style - error: "+req.readyState);
    }
  }

  req.open("GET",(cordova.file.dataDirectory+"geoita.json"),true);
  req.send();

TEST 3 (follow official guideline)测试 3(遵循官方指南)

Result: file not found or encoding error.结果:找不到文件或编码错误。

const filePath = cordova.file.applicationDirectory+"geoita.json"; //return error code 5 ENCODING_ERR
//const filePath = "www/geoita.json"; // return error  1 NOT_FOUND_ERR
//const filePath ="geoita.json"; 
//const filePath = cordova.file.applicationDirectory+"geoita.txt"; // not changed

window.resolveLocalFileSystemURL( filePath ,
fileEntry => {

  console.log("file object ready");

  fileEntry.file(
    File => {

      console.log("content: ",File);

      var reader = new FileReader();
      reader.onloadend = function(evt)
      {
          console.log("read success",evt.target.result);
      };
      reader.readAsText(File);

    });

}, error => console.error(error) );

I'm continuing to do many tests but I don't understand what is going wrong.我继续做很多测试,但我不明白出了什么问题。 I don't understand why it is so difficult to read a local file in the www folder of Cordova.我不明白为什么读取Cordova 的www 文件夹中的本地文件如此困难。

How can I do this?我怎样才能做到这一点?

Update更新

Over 32 tests after, the solution was wrong.经过32次测试,解决方案是错误的。

Unfortunately I just realized that he doesn't write the file from the www folder.不幸的是,我刚刚意识到他没有从 www 文件夹中写入文件。 What you can do is "create a file from the variable, historicize it in the permanent and then reread it. It still doesn't read as I wanted then.您可以做的是“从变量创建一个文件,将其历史化,然后重新读取它。它仍然没有按照我想要的方式读取。

What happened during the test is simply the result of previous tests where I had "copied the file into the variable by hand", therefore I had unknowingly saved it and was subsequently recovered as if it were reading the local one (which, of course, was identical)测试期间发生的事情只是之前测试的结果,我“手动将文件复制到变量中”,因此我在不知不觉中保存了它,随后被恢复,好像它正在读取本地文件(当然,是相同的)

Unfortunately I still can't find a solution to read the file.不幸的是,我仍然找不到读取文件的解决方案。 If you are aware of it, write!如果你知道它,写!

For this example we have 2 type of data.对于这个例子,我们有 2 种类型的数据。

1) is a simple var within a json message; 1) 是 json 消息中的一个简单变量;

2) It's a local file in the directory www (then create a file by hand that you can recover ... a text with false json data similar to the one in 1) 2)它是www目录下的本地文件(然后手工创建一个可以恢复的文件......一个类似于1合1的带有假json数据的文本)

Step 00步骤 00

add cordova-file-plugin in your project在您的项目中添加cordova-file-plugin

https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html

Step 01步骤 01

In config.xml在 config.xml 中

  <platform name="android">
        <preference name="AndroidPersistentFileLocation" value="Compatibility" />
        <preference name="AndroidExtraFilesystems" value="assets,root, files, cache, sdcard, cache-external, files-external" />
    </platform>
    <platform name="ios">
        <preference name="iosPersistentFileLocation" value="Compatibility" />
        <preference name="iosExtraFilesystems" value="assets,root, files,cache, sdcard, cache-external, files-external" />
    </platform>

Potentially you may also need to enter:您可能还需要输入:

<access origin="*" /> <access origin="cdvfile://*"/> <access origin="file:///*"/>

Step 02步骤 02

Now, after app is ready, example:现在,在应用程序准备好后,例如:

  if('cordova' in window)
  {
    document.addEventListener('deviceready', mytest);
    // console.log('device');
  }
  else
  {
    document.addEventListener('DOMContentLoaded', mytest);
    // console.log('web device');
  }

in alternative joint it on event:或者在事件中联合它:

  document.addEventListener('click', mytest,true);
  document.addEventListener('touchstart', mytest,true);

Step 03步骤 03

Into your function of app进入你的应用功能

  function mytest(){


      // start for read (get the file and pass it on readFile method)
      window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
      (fs)=> {

        var fileName = "test.txt",
            fileDir =  cordova.file.applicationDirectory.replace( cordova.file.applicationDirectory, ''), //cordova.file.applicationDirectory only get error on entry file
            filePath = fileDir + fileName;

        fs.root.getFile(
          filePath,
          null,
          (fileEntry) => {
            readFile(fileEntry)
          }, fileEntryFail);

      }, filesystemFail);



      // start for write (set a file creator -> get data via var -> pass var on writeFile method)
      window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
      (fs)=> {

        var fileName = "test.txt",
            fileDir =  cordova.file.applicationDirectory.replace( cordova.file.applicationDirectory, ''), //cordova.file.applicationDirectory only get error on entry file
            filePath = fileDir + fileName;

        fs.root.getFile(
          filePath,
          { create: true, exclusive: false },
          (fileEntry) => {
            writeFile(fileEntry, filetowrite );
          }, fileEntryFail);

      }, filesystemFail);



      // write a file whit data
      function writeFile(fileEntry, dataObj) {
          fileEntry.createWriter(function (fileWriter) {

              fileWriter.onwrite = function() {
                  alert("file write");
                  // readFile(fileEntry); // if you wont read after write it
              };

              fileWriter.onerror = function (e) {
                  alert("Failed file write: " + e.toString());
              };

              fileWriter.write(dataObj);
          });
      }



      // read a file getted 
      function readFile(fileEntry) {

        alert('Reading file....');

        fileEntry.file(function (fileEntry)
        {

            console.log("path to file: ",fileEntry.fullPath);
            console.log("file to read: ",fileEntry.file);

            var reader = new FileReader();
            reader.onloadend = function()
            {
                alert("Successful file read");
                // document.body.innerHTML = ""+this.result;
                console.log("Successful file read: ",this.result);
                // window.dataActive = JSON.parse(this.result);
                // alert('dataActive was read as: ' + dataActive)
                // displayFileData(fileEntry.fullPath + ": " + this.result);
            };
            reader.readAsText(fileEntry);

        }, readFail );

      };


      // fails 
      function filesystemFail (err) { alert("FS: DATA FAIL"); console.log(err.code);};
      function fileEntryFail (err) { alert("File entry: FAIL"); };
      function writeFail (err) { alert("Writing: DATA FAIL"); };
      function readFail (err) { alert("Reading: DATA FAIL"); };


      //data test via var
      var filetowrite =  `{"message": "THIS IS SIMPLE TEST MESSAGE"}`

    };  

Now some important closing notes现在一些重要的结束笔记

It is obviously useless to keep both start read and start write which test on the same file or data.在同一个文件或数据上同时保持 start read 和 start write 显然是没用的。 Either write the file and then read it or take it locally and read it directly.要么写入文件然后读取它,要么在本地获取它并直接读取它。 So for your tests comment one of the two at a time.因此,对于您的测试,一次评论两个中的一个。

It's also stupid to keep them separate because it would be easy to optimize the system by calling the file system only once.将它们分开也很愚蠢,因为只需调用一次文件系统就可以很容易地优化系统。

However, I left them separate to give a clear and functional example to those who, like me, are stuck on logic.但是,我将它们分开,以便为那些像我一样坚持逻辑的人提供一个清晰而实用的示例。

Update更新

Solution:解决方案:

While waiting for the whole plugin I am testing to be built:在等待构建我正在测试的整个插件时:

A) you have to "unlock" access to files in config.xml as I explained above. A)你必须“解锁”对 config.xml 中文件的访问,正如我上面所解释的。

B) cordova-file-plugin can only write, read, delete files in the permanent memory inside the app. B)cordova-file-plugin 只能在应用程序内部的永久内存中写入、读取、删除文件。 (I will release a better model than the one above as soon as I can) (我会尽快发布比上面更好的模型)

C) fetch does not work in any case. C) fetch 在任何情况下都不起作用。 BE CAREFUL, it only works on the browser but not in the app小心,它只适用于浏览器而不适用于应用程序

D-1) I am testing the writing and deleting of files in the www. D-1) 我正在测试 www 中文件的写入和删除。 I still need time.我还需要时间。

D-2) it is possible to read through an XML request the file in the www in the following way: D-2) 可以通过以下方式通过 XML 请求读取 www 中的文件:

var _filename = 'MYFILENAMEINWWW.txt',
    _mimetype = 'text/plain'; // or application/json

    function readfromwww(_mimetype,_filename,callback)
    {


        var request = new XMLHttpRequest();
            request.overrideMimeType(_mimetype ); 
            request.open("GET", _filename );
            request.onreadystatechange = () =>
            {

              if(request.status > 300)
              {
                if(rs==404) console.log('file not found in www: ',request.status);
                else console.log('error on request: ',request.status);
              }

              else if(request.responseText!=undefined && request.responseText!='')
              {

                //from json string to js obj content
                if(_mimetype == "application/json")
                  callback(JSON.parse(request.responseText));

                //return string into your file
                else
                  callback(request.responseText);

              }

            }
            request.send();

          }

    }

          // now you can read a file in www calling the method:

          readfromwww('text/plain', 'test.txt',
            filecontent => {

               console.log('OLE! INTO THE FILE: ',filecontent);

               //not filecontent is the content of your file but... remember... the contents is loaded via ajax, isn't easy to storize it out this function.

            });

You can check out MongOGX which is a front end db inspired by MongoDB where you can save JSON documents and it supports cordova您可以查看 MongOGX,这是一个受 MongoDB 启发的前端数据库,您可以在其中保存 JSON 文档并支持cordova

MongOGX is a simple JavaScript based document store/database inspired by MongoDB. MongOGX 是一个简单的基于 JavaScript 的文档存储/数据库,受 MongoDB 启发。 It supports local storage and application data storage (via Cordova - cordova-plugin-file) storage modes.它支持本地存储和应用程序数据存储(通过 Cordova -cordova-plugin-file)存储模式。 It also supports encryption (via code.google.com/p/crypto-js - added to this repo).它还支持加密(通过 code.google.com/p/crypto-js - 添加到此存储库中)。

See https://github.com/globules-io/MongOGXhttps://github.com/globules-io/MongOGX

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM