Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. SerialPortReader output in a text file
QtWS25 Last Chance

SerialPortReader output in a text file

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 6 Posters 646 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.
  • D Offline
    D Offline
    Denta1000
    wrote on last edited by
    #1

    Hi there,

    I'm a newbie on Qt and I'm trying to read a serial port and write the datas into a text file. I started from Qt's example "creaderasync" and now I'm blocked when it comes to associate my opened file with the QTextStream m_standardOuput element of the SerialPortReader class.
    I'm using QtCreator 5.15.2 on Windows 10.

    Here is the modified serialportreader.h :

    #ifndef SERIALPORTREADER_H
    #define SERIALPORTREADER_H
    
    #include <QObject>
    #include <QByteArray>
    #include <QSerialPort>
    #include <QTextStream>
    #include <QTimer>
    #include <QFile>
    
    QT_BEGIN_NAMESPACE
    
    QT_END_NAMESPACE
    
    void serial_start(QSerialPort* serialPort,QObject* parent = nullptr);
    
    class SerialPortReader : public QObject
    {
        Q_OBJECT
    
    public:
        explicit SerialPortReader();
        SerialPortReader(QSerialPort *serialPort, QObject* parent = nullptr);
    
    public slots:
        void handleReadyRead();
        void handleTimeout();
        void handleError(QSerialPort::SerialPortError error);
    
    private:
        QSerialPort *m_serialPort = nullptr;
        QByteArray m_readData;
        QFile file;
        QTextStream m_standardOutput;
        QTimer m_timer;
    };
    
    #endif // SERIALPORTREADER_H
    

    and here is the modified serialportreader.cpp :

    #include "serialportreader.h"
    #include <QCoreApplication>
    #include <QDebug>
    #include <QFile>
    #include <QObject>
    #include <QByteArray>
    #include <QSerialPort>
    #include <QTextStream>
    #include <QTimer>
    
    SerialPortReader::SerialPortReader(QSerialPort* serialPort,QObject* parent)
        : QObject(parent), m_serialPort(serialPort), file("file.txt"), m_standardOutput(&file) //construction of FILE and linking with m_standardOutput using QTextStream's  constructor
    
    {
        if(!file.open(QIODevice::WriteOnly | QIODevice::Append)){ //test file opening
            qDebug() << "can't open file.txt \n";
        }
    
        qDebug() << file.fileName() << "opened";
        m_standardOutput << "First test out \n"; //first try writing into the file
    
         //usual SerialPortReader connections
        connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead);
        connect(&m_timer, &QTimer::timeout, this, &SerialPortReader::handleTimeout);
        connect(m_serialPort, &QSerialPort::errorOccurred, this, &SerialPortReader::handleError);
    
        qDebug() << "connection done\n";
        qDebug() << "timer set\n";
        m_timer.start(5000);
    }
    
    void SerialPortReader::handleReadyRead()
    {
        //qDebug () << "handleReadyRead \n";
        m_standardOutput << "second test out" << "\n"; //second try writing into the file , meant to write serialport's content in the futur
    
    // datas receiving verification
        m_readData = m_serialPort->readAll();
        qDebug () << m_readData;              
        //m_serialPort->flush();
        m_timer.start(5000);
    }
    
    void SerialPortReader::handleTimeout()
    {
    /* Original example's definition...*/
        QCoreApplication::quit();
    }
    
    void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError)
    {
    /* Original example's definition...*/
            QCoreApplication::exit(1);
        }
    }
    
    

    The buil step is ok. It runs well since I can see my serial port's datas on my qDebug() terminal. The file file.txt is created in my build folder but it contains nothing...
    After some research, I thought it could be because I construct m_standardOutput(&file) before calling file.open(QIODevice...) . But I can't find a solution to do it the opposite way.

    I hope I didn't forget any important detail.

    Thank you in advance for your support !

    jsulmJ 1 Reply Last reply
    0
    • D Denta1000

      Hi there,

      I'm a newbie on Qt and I'm trying to read a serial port and write the datas into a text file. I started from Qt's example "creaderasync" and now I'm blocked when it comes to associate my opened file with the QTextStream m_standardOuput element of the SerialPortReader class.
      I'm using QtCreator 5.15.2 on Windows 10.

      Here is the modified serialportreader.h :

      #ifndef SERIALPORTREADER_H
      #define SERIALPORTREADER_H
      
      #include <QObject>
      #include <QByteArray>
      #include <QSerialPort>
      #include <QTextStream>
      #include <QTimer>
      #include <QFile>
      
      QT_BEGIN_NAMESPACE
      
      QT_END_NAMESPACE
      
      void serial_start(QSerialPort* serialPort,QObject* parent = nullptr);
      
      class SerialPortReader : public QObject
      {
          Q_OBJECT
      
      public:
          explicit SerialPortReader();
          SerialPortReader(QSerialPort *serialPort, QObject* parent = nullptr);
      
      public slots:
          void handleReadyRead();
          void handleTimeout();
          void handleError(QSerialPort::SerialPortError error);
      
      private:
          QSerialPort *m_serialPort = nullptr;
          QByteArray m_readData;
          QFile file;
          QTextStream m_standardOutput;
          QTimer m_timer;
      };
      
      #endif // SERIALPORTREADER_H
      

      and here is the modified serialportreader.cpp :

      #include "serialportreader.h"
      #include <QCoreApplication>
      #include <QDebug>
      #include <QFile>
      #include <QObject>
      #include <QByteArray>
      #include <QSerialPort>
      #include <QTextStream>
      #include <QTimer>
      
      SerialPortReader::SerialPortReader(QSerialPort* serialPort,QObject* parent)
          : QObject(parent), m_serialPort(serialPort), file("file.txt"), m_standardOutput(&file) //construction of FILE and linking with m_standardOutput using QTextStream's  constructor
      
      {
          if(!file.open(QIODevice::WriteOnly | QIODevice::Append)){ //test file opening
              qDebug() << "can't open file.txt \n";
          }
      
          qDebug() << file.fileName() << "opened";
          m_standardOutput << "First test out \n"; //first try writing into the file
      
           //usual SerialPortReader connections
          connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead);
          connect(&m_timer, &QTimer::timeout, this, &SerialPortReader::handleTimeout);
          connect(m_serialPort, &QSerialPort::errorOccurred, this, &SerialPortReader::handleError);
      
          qDebug() << "connection done\n";
          qDebug() << "timer set\n";
          m_timer.start(5000);
      }
      
      void SerialPortReader::handleReadyRead()
      {
          //qDebug () << "handleReadyRead \n";
          m_standardOutput << "second test out" << "\n"; //second try writing into the file , meant to write serialport's content in the futur
      
      // datas receiving verification
          m_readData = m_serialPort->readAll();
          qDebug () << m_readData;              
          //m_serialPort->flush();
          m_timer.start(5000);
      }
      
      void SerialPortReader::handleTimeout()
      {
      /* Original example's definition...*/
          QCoreApplication::quit();
      }
      
      void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError)
      {
      /* Original example's definition...*/
              QCoreApplication::exit(1);
          }
      }
      
      

      The buil step is ok. It runs well since I can see my serial port's datas on my qDebug() terminal. The file file.txt is created in my build folder but it contains nothing...
      After some research, I thought it could be because I construct m_standardOutput(&file) before calling file.open(QIODevice...) . But I can't find a solution to do it the opposite way.

      I hope I didn't forget any important detail.

      Thank you in advance for your support !

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

      @Denta1000 There is an example in the documentation (https://doc.qt.io/qt-5/qtextstream.html):

      QFile data("output.txt");
      if (data.open(QFile::WriteOnly | QFile::Truncate)) {
          QTextStream out(&data);
          out << "Result: " << qSetFieldWidth(10) << left << 3.14 << 2.7;
          // writes "Result: 3.14      2.7       "
      }
      

      So, in constructor open the file (make the QFile instance class member) and pass the pointer to it as parameter to QTextStream.

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

      J.HilkJ 1 Reply Last reply
      1
      • jsulmJ jsulm

        @Denta1000 There is an example in the documentation (https://doc.qt.io/qt-5/qtextstream.html):

        QFile data("output.txt");
        if (data.open(QFile::WriteOnly | QFile::Truncate)) {
            QTextStream out(&data);
            out << "Result: " << qSetFieldWidth(10) << left << 3.14 << 2.7;
            // writes "Result: 3.14      2.7       "
        }
        

        So, in constructor open the file (make the QFile instance class member) and pass the pointer to it as parameter to QTextStream.

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #3

        @jsulm you can see, the OP actually does that, in the initializer list

        @Denta1000 QTesxtStream has a setDevice() function, use that to set the device after you open it, see if that helps 🤷‍♂️


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        jsulmJ 1 Reply Last reply
        2
        • J.HilkJ J.Hilk

          @jsulm you can see, the OP actually does that, in the initializer list

          @Denta1000 QTesxtStream has a setDevice() function, use that to set the device after you open it, see if that helps 🤷‍♂️

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

          @J-Hilk Ah, you're right, need more coffee :-)

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

          J.HilkJ 1 Reply Last reply
          1
          • jsulmJ jsulm

            @J-Hilk Ah, you're right, need more coffee :-)

            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by
            #5

            @jsulm said in SerialPortReader output in a text file:

            @J-Hilk Ah, you're right, need more coffee :-)

            😜

            I'm out of coffee, thank god, today is a short work day!


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              Denta1000
              wrote on last edited by
              #6

              @jsulm @J-Hilk thanks for your help,

              I tried using setdevice() but it changed nothing.
              So far, I constructed a second QTextStream linked to the same file, before file.open() to verify my hypothesis :
              *

              QTextStream out(&file); //constructed before file opening
              
              if(!file.open(QIODevice::WriteOnly | QIODevice::Append)){ //test file opening
                  qDebug() << "can't open fichier.txt \n";
              }
              
              
              qDebug() << file.fileName() << "opened"; //test opening success
              
              qDebug() << "out associated Device : " << out.device(); //First QTextStream infos
              qDebug() << "out status : " << out.status();
              out << "First test";
              
              m_standardOutput.setDevice(out.device()); // setdevice() after file opening
              qDebug() << "m_standard associated device : " << m_standardOutput.device();
              qDebug ()<< "m_standard status : " << m_standardOutput.status();
              m_standardOutput << "second test \n";*
              

              Here QTextStream out is constructed before file.open() , and yet it does write into file.
              Whereas, m_standardOutput.setdevice() is used after the file opening and m_standarOutput still doesn't write into the file.

              qDebug output shows that the two QTextStreams are similar :

              f6fb079c-d7d3-4da9-b05b-035e7b510d5b-image.png

              According to QTextStream:: , status 0 means "The text stream is operating normally."

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Denta1000
                wrote on last edited by
                #7

                I tried setting m_standardOutput as a QTextStream pointer :

                QTextStream out(&file);
                    m_standardOutput = &out;
                

                and then I call :

                *m_StandardOutput << "Second test";
                

                It does write into the file when used in the SerialPortReader constructor.
                So I called "*m_standardOutput <<" in the SerialPortReader::handleReadyRead().

                void SerialPortReader::handleReadyRead()
                {
                
                    //qDebug() << "device inside handleReadyRead : " << m_standardOutput->device();
                    *m_standardOutput << "deuxieme test out \n" ; //second try writing into the file , meant to write serialport content in the futur
                
                    m_readData = m_serialPort->readAll(); // datas receiving verification
                    qDebug () << m_readData;
                    //m_serialPort->flush();
                    m_timer.start(5000);
                }
                

                But as soon as the program encounters a command involving m_standardOutput inside the HandleReadyRead() part, it blocks...

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Hi,

                  @Denta1000 said in SerialPortReader output in a text file:

                  QTextStream out(&file);
                  m_standardOutput = &out;

                  You realize that you are taking the address of a local and thus temporary object that will be destroyed at the end of the method it was created in ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  D 1 Reply Last reply
                  1
                  • SGaistS SGaist

                    Hi,

                    @Denta1000 said in SerialPortReader output in a text file:

                    QTextStream out(&file);
                    m_standardOutput = &out;

                    You realize that you are taking the address of a local and thus temporary object that will be destroyed at the end of the method it was created in ?

                    D Offline
                    D Offline
                    Denta1000
                    wrote on last edited by
                    #9

                    Hi, @SGaist
                    Do you mean that QTextStream out is destroyed when the SerialPortReader constructor is done and so the link to write into the file ?

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      Yes it is destroyed since it's variable that is local to the constructor.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0
                      • D Offline
                        D Offline
                        Denta1000
                        wrote on last edited by Denta1000
                        #11

                        Well , in fact it sounds logical...
                        Then I should juste have to construct the link beetween m_standardOutput and file since they are both part of the SerialPortReader object
                        But m_standardOutput doesn't write anything in the file, even during the constructor part.

                        SerialPortReader::SerialPortReader(QSerialPort* serialPort,QObject* parent)
                            : QObject(parent), m_serialPort(serialPort), file("file.txt"),m_standardOutput(&file) //construction of FILE and linking with QTextStream m_standardOutput
                        {
                        
                            if(!file.open(QIODevice::WriteOnly | QIODevice::Append)){ //test file opening
                                qDebug() << "can't open fichier.txt \n";
                            }
                            //m_standardOutput.setDevice(&file);
                            qDebug() << file.fileName() << "opened";
                            qDebug() << "file permissions :" << file.permissions() << "\n";
                        
                            m_standardOutput << "test 2";
                        
                            qDebug() << "m_standard associated device : " << m_standardOutput.device();
                            qDebug ()<< "m_standard status : " << m_standardOutput.status();
                        

                        This part of the code should be sufficient to write the "test 2" text in the file but it doesn't, even though qDebug shows that the link is correct...

                        29e2b616-10a5-46f0-97e9-c94d0bcc3e35-image.png

                        JonBJ 1 Reply Last reply
                        0
                        • D Denta1000

                          Well , in fact it sounds logical...
                          Then I should juste have to construct the link beetween m_standardOutput and file since they are both part of the SerialPortReader object
                          But m_standardOutput doesn't write anything in the file, even during the constructor part.

                          SerialPortReader::SerialPortReader(QSerialPort* serialPort,QObject* parent)
                              : QObject(parent), m_serialPort(serialPort), file("file.txt"),m_standardOutput(&file) //construction of FILE and linking with QTextStream m_standardOutput
                          {
                          
                              if(!file.open(QIODevice::WriteOnly | QIODevice::Append)){ //test file opening
                                  qDebug() << "can't open fichier.txt \n";
                              }
                              //m_standardOutput.setDevice(&file);
                              qDebug() << file.fileName() << "opened";
                              qDebug() << "file permissions :" << file.permissions() << "\n";
                          
                              m_standardOutput << "test 2";
                          
                              qDebug() << "m_standard associated device : " << m_standardOutput.device();
                              qDebug ()<< "m_standard status : " << m_standardOutput.status();
                          

                          This part of the code should be sufficient to write the "test 2" text in the file but it doesn't, even though qDebug shows that the link is correct...

                          29e2b616-10a5-46f0-97e9-c94d0bcc3e35-image.png

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @Denta1000 said in SerialPortReader output in a text file:

                          should be sufficient to write the "test 2" text in the file but it doesn't

                          I don't really understand why you're saying anything is wrong. It reports status OK, what is it that makes you say something has gone wrong? I wouldn't expect to see anything in the file till you've closed or at least flushed it, if that's what you're looking at.

                          1 Reply Last reply
                          1
                          • D Offline
                            D Offline
                            Denta1000
                            wrote on last edited by
                            #13

                            @JonB thanks a lot, it was all because I wouldn't close the file properly. But I thought I read that file.close flushes the file. Doesn't "flush" means the file's content get destroyed ?

                            Thanks a lot, even if I feel a bit ashamed now ... ^^'

                            How do I make the post Resolved ?

                            mrjjM JonBJ 2 Replies Last reply
                            0
                            • D Denta1000

                              @JonB thanks a lot, it was all because I wouldn't close the file properly. But I thought I read that file.close flushes the file. Doesn't "flush" means the file's content get destroyed ?

                              Thanks a lot, even if I feel a bit ashamed now ... ^^'

                              How do I make the post Resolved ?

                              mrjjM Offline
                              mrjjM Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              @Denta1000

                              Hi
                              Flushing a file means making sure all buffers are saved to disk.
                              Often file IO has buffers and flushing means to get all data on the disk.

                              Often closing the file will also make it flush first.

                              • How do I make the post Resolved ?

                              In the first post. There is Topic Tool button that make flag as solved.

                              1 Reply Last reply
                              1
                              • D Denta1000

                                @JonB thanks a lot, it was all because I wouldn't close the file properly. But I thought I read that file.close flushes the file. Doesn't "flush" means the file's content get destroyed ?

                                Thanks a lot, even if I feel a bit ashamed now ... ^^'

                                How do I make the post Resolved ?

                                JonBJ Offline
                                JonBJ Offline
                                JonB
                                wrote on last edited by JonB
                                #15

                                @Denta1000
                                When you send bytes to a QTextStream they are in memory in a buffer, not yet in disk file. You can call QTextStream::flush() to

                                Flushes any buffered data waiting to be written to the device.

                                Flushing here does not mean discarding pending-written data, it only means flushing it from memory to disk.

                                I believe that rather than sending the "\n" which you do, endl would flush:

                                m_standardOutput << "second test out" << endl;
                                

                                You should call QFile::close() to close the backing file. There may be buffering going on in QFile as well as in QTextStream, I don't know. There is a QIODevice::Unbuffered flag which can be passed when opening QFile. Nor do I know whether you need to call QTextStream::flush() before closing the file.

                                You would have to play to find out how QTextStream and QFile interact for all this buffering/flushing!

                                1 Reply Last reply
                                2

                                • Login

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