Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Android .txt resource file editing in Qt
Forum Updated to NodeBB v4.3 + New Features

Android .txt resource file editing in Qt

Scheduled Pinned Locked Moved Solved Mobile and Embedded
androidqt qfile
12 Posts 4 Posters 2.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    monster
    wrote on last edited by A Former User
    #1

    Can I add a blank file "Orders.txt" to .qrc resources, and then edit it in application? What will happen after the application restart? Will the text in file remain in the next application startup?

    I mean - I want to create an order database. On the beginning of the file there will be a number of orders actually made. In the next lines will be records. Every record has 3 parts, and every part take one line in the file, so 3 lines are for one record.

    I actually have one version of my application, but it doesn't work. I test it by writing one record to file and then by reading it. When I try to list record fields, I'm getting blank strings.

    Thank you for your help.

    1 Reply Last reply
    0
    • M Offline
      M Offline
      monster
      wrote on last edited by
      #2

      ORDERPROCEDURES.H:

      #ifndef ORDERPROCEDURES_H
      #define ORDERPROCEDURES_H
      
      #include <QObject>
      #include <QQuickItem>
      #include <QTextStream>
      
      
      struct Order_Details {
           uint16_t order_number;
           char product_number;
           QString name_surname;
           QString email_adress;
      };
      
      
      class OrderProcedures : public QObject
      {
          Q_OBJECT
      public:
          explicit OrderProcedures(QObject *parent = 0);
          Q_INVOKABLE bool UpdateOrdersCount(const QString &filename);
          Q_INVOKABLE Order_Details ReadOneRecord(const QString &filename, uint16_t record_number);
          Q_INVOKABLE bool WriteOneRecord(const QString &filename, Order_Details &details, char tproduct_number);
          Q_INVOKABLE bool ReadAllOrders(const QString &filename);
      
      signals:
      
      public slots:
      private:
          uint16_t order_count = 0;
          Order_Details order_table[sizeof(uint16_t)];
      };
      
      
      
      #endif // ORDERPROCEDURES_H
      

      ORDERPROCEDURES.CPP

      #include "orderprocedures.h"
      
      OrderProcedures::OrderProcedures(QObject *parent) : QObject(parent)
      {
      
      }
      bool OrderProcedures::UpdateOrdersCount(const QString &filename)
      {
          char buffer[2];
          QFile file(filename);
          if (!file.open(QIODevice::ReadOnly))
              return false;
      
          if (!file.getChar(&buffer[0]))  //buffering the file data connected with number of orders
              return false;
          if (!file.getChar(&buffer[1]))
              return false;
      
          memcpy(&order_count, buffer, sizeof(uint16_t)); //setting the current number of orders
      
          file.close();
          return true;
      
      }
      
      Order_Details OrderProcedures::ReadOneRecord(const QString &filename, uint16_t record_number)
      {
          Order_Details detailsoforder;
          detailsoforder.name_surname="";
          detailsoforder.email_adress="";
      
          if(record_number>order_count)   //break if there is no such record
              return detailsoforder;
      
          QFile file(filename);           //break if it is impossible to open file
          if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
              return detailsoforder;
      
          if (!file.canReadLine())        //break if there is nothing in the file
              return detailsoforder;
      
          file.readLine();                //skip first line with numbers
      
      
          for(uint16_t i=0 ; i<record_number ; i++)
          {
              file.readLine();            //skip lines with data that we aren't interested in
              file.readLine();
              file.readLine();
          }
      
          file.getChar(&(detailsoforder.product_number));  //getting the number of order Ist ROW
          file.readLine();                //skipping "\n"
      
          QString nas = file.readLine();  //buffering names and email
          QString ead = file.readLine();
      
          detailsoforder.name_surname.resize(nas.size()-1);   //resizing, throwing away "/n" character
          detailsoforder.email_adress.resize(ead.size()-1);
          for (uint16_t i=0 ; i<nas.size() ; i++)
          {
              detailsoforder.name_surname[i]=nas[i];
          }
          for (uint16_t i=0 ; i<nas.size() ; i++)
          {
              detailsoforder.email_adress[i]=ead[i];
          }
      
          file.close();               //closing the file
          return detailsoforder;
      }
      
      bool OrderProcedures::WriteOneRecord(const QString &filename, Order_Details &details, char tproduct_number)
      {
          char buffer[2];
          QFile file(filename);
          if (!file.open(QIODevice::Append | QIODevice::Text))
              return false;
      
      
          if(order_count<sizeof(uint16_t)-2)
              order_count++;                              //order counter incrementing
          else
              return false;                               //overflow - no more place for records
      
          memcpy(buffer, &order_count, sizeof(uint16_t)); //order counter buffering
      
          QTextStream writer(&file);
      
          file.putChar(tproduct_number);
          file.putChar('\n');
          writer<<details.name_surname<<"\n";             //appending order
          writer<<details.email_adress<<"\n";
          file.close();                                   //closing file
      
      
          if (!file.open(QIODevice::WriteOnly))           //opening again to write on the begginning
              return false;
      
          if (!file.putChar(buffer[0]))                   //updating order counter
          {
              order_count--;
              return false;
          }
          if (!file.putChar(buffer[1]))
          {
              order_count--;
              return false;
          }
          if (!file.putChar('\n'))
          {
              order_count--;
              return false;
          }
      
          file.close();
      
          order_table[order_count-1].name_surname.resize(details.name_surname.size());   //resizing the database record
          order_table[order_count-1].email_adress.resize(details.email_adress.size());
      
          order_table[order_count-1].product_number=tproduct_number;
          order_table[order_count-1].name_surname=details.name_surname;                  //updating the database with the current record
          order_table[order_count-1].email_adress=details.email_adress;
          return true;
      }
      
      bool OrderProcedures::ReadAllOrders(const QString &filename)
      {
          if(!UpdateOrdersCount(filename))
              return false;
      
          QFile file(filename);           //break if it is impossible to open file
          if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
              return false;
      
          if (!file.canReadLine())        //break if there is nothing in the file
              return false;
      
          file.readLine();                //skip first line with numbers
      
          for(uint16_t i =0 ; i<order_count ; i++)
          {
              file.getChar(&(order_table[i].product_number));  //getting the number of order Ist ROW
              file.readLine();                //skipping "\n"
      
              QString nas = file.readLine();  //buffering names and email
              QString ead = file.readLine();
      
              order_table[i].name_surname.resize(nas.size()-1);   //resizing, throwing away "/n" character
              order_table[i].email_adress.resize(ead.size()-1);
      
              for (uint16_t j=0 ; i<nas.size() ; j++)
              {
                  order_table[i].name_surname[j]=nas[j];
              }
              for (uint16_t j=0 ; j<nas.size() ; j++)
              {
                  order_table[i].email_adress[j]=ead[j];
              }
          }
      
          file.close();
      
          return true;
      }
      
      

      MAIN.CPP:

      #include <QApplication>
      #include <QQmlApplicationEngine>
      #include <orderprocedures.h>
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
          OrderProcedures all;
      
          Order_Details detale;
          detale.name_surname.resize(15);
          detale.email_adress.resize(15);
          detale.name_surname="Jan Kowalski";
          detale.email_adress="jk@wp.pl";
          detale.product_number=1;
      
          all.UpdateOrdersCount("Orders.txt");
          all.WriteOneRecord("Orders.txt",detale,'1');
      
          Order_Details detale2 = all.ReadOneRecord("Orders.txt",1);
      
          //QTextStream out(stdout);
          qWarning()<<"llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"<<"\n"; //For me to notice warnings in console
          qWarning()<<detale2.product_number;
          qWarning()<<detale2.name_surname;
          qWarning()<<detale2.email_adress;
      
          QQmlApplicationEngine engine;
          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
          return app.exec();
      }
      

      AND THE TESTING OUTPUT

      W libandroidtestQML.so: ../androidtestQML/main.cpp:23 (int main(int, char**)): llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
      01-11 08:45:58.307  1418  1455 W libandroidtestQML.so:
      W libandroidtestQML.so: ../androidtestQML/main.cpp:24 (int main(int, char**)):
      W libandroidtestQML.so: ../androidtestQML/main.cpp:25 (int main(int, char**)): ""
      W libandroidtestQML.so: ../androidtestQML/main.cpp:26 (int main(int, char**)): ""
      1 Reply Last reply
      0
      • jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        I may be wrong but as far as I know on Android you cannot write in the directory where your app is installed (for security reasons). The qrc file is part of your application, so I guess it will not work this way. You should use a directory where your app has write access.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • M Offline
          M Offline
          monster
          wrote on last edited by
          #4

          I see. So am I able to create a blank file in the application when it starts for the first time and then to edit it when it actually exists in the given location? How should I do it?

          1 Reply Last reply
          0
          • jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Check this one on Android:

            QString QStandardPaths::writableLocation(StandardLocation type)
            Call it like this:
            QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
            

            More here: http://doc.qt.io/qt-5/qstandardpaths.html

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            1
            • M Offline
              M Offline
              monster
              wrote on last edited by
              #6

              Thank you a LOT! Especially for Standard Paths. It works :) I've got last small question. I've noticed that I understand file operation modes wrong. Writing in append mode seems easy. As a ReadOnly mode, I understand the mode in which you start reading the file from the beggining. But now I found that WriteOnly mode erases all file and starts writing from the beginning! Is that right? I thought that WriteOnly opens the file with pointer pointing the beginning of file, and so I thought that writing in that mode allows me to replace previously written characters. I want to find the mode that allows me to change the number at the beginning without writing whole file again...

              jsulmJ 1 Reply Last reply
              0
              • M Offline
                M Offline
                monster
                wrote on last edited by
                #7

                Sorry that I've got even more questions :D

                Can I declare structures with QStrings and then resize them inside that structure? Does structure also resize itself then?

                Am I correct that I don't have to resize the QString when I declare:
                QString valuvalue = somekindofcharorstring;
                ?
                It changes its size automatically, am I right?

                1 Reply Last reply
                0
                • stackprogramerS Offline
                  stackprogramerS Offline
                  stackprogramer
                  wrote on last edited by stackprogramer
                  #8

                  hi,i offer, you can use xml or json for saving your data
                  Data storage

                  1 Reply Last reply
                  1
                  • M Offline
                    M Offline
                    monster
                    wrote on last edited by
                    #9

                    I'm afraid that it is too big amount of knowledge for such a small project, but I will consider it, thank you :)

                    1 Reply Last reply
                    0
                    • K Offline
                      K Offline
                      kornava
                      wrote on last edited by
                      #10

                      I think it can be much easier with LocalStorage , it can be done entirely from QML:
                      http://qmlbook.github.io/en/ch12/index.html#local-storage-sql

                      I think this is the simpler solution to establish saving ability for an app, but you can't access the stored information from outside your app.

                      1 Reply Last reply
                      0
                      • M monster

                        Thank you a LOT! Especially for Standard Paths. It works :) I've got last small question. I've noticed that I understand file operation modes wrong. Writing in append mode seems easy. As a ReadOnly mode, I understand the mode in which you start reading the file from the beggining. But now I found that WriteOnly mode erases all file and starts writing from the beginning! Is that right? I thought that WriteOnly opens the file with pointer pointing the beginning of file, and so I thought that writing in that mode allows me to replace previously written characters. I want to find the mode that allows me to change the number at the beginning without writing whole file again...

                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        @monster Use

                        QIODevice::WriteOnly | QIODevice::Append
                        

                        Then the file should not be overwritten.

                        You can declare structures containing strings. The size of the struct does not depend on the size of stored strings, because internally QString stores the actual string on the heap and just points to it. On my machine sizeof(StrStruct) is 16 (StrStruct contains two QString members). So it is 2 * sizeof(void*).

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        1
                        • M Offline
                          M Offline
                          monster
                          wrote on last edited by
                          #12

                          Thank you all. Everything works fine. I just corrected my old, first example. There were many problems. I can upload example that works, and correctly fills and reads file according to the picked scheme if anybody is interested.

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved