Read a byte from a .txt and store it as it is in an integer.



  • Qt's overcomplicated software makes it again impossible for me to do the most simple task.

    I need my application to remember in which language it is set. I do this with an .ini file. Initially I did it with characters and it worked for language 0 to 9. But from 10 and higher....

    Than I thought, gee why so complicated, it does not have to be human-readable. So I just want to read out one whole byte out of the text file and stuff the value of that byte in an integer variable. How hard can it be right?

    I have the storing part working but the reading part seems to be impossible.

    QFile setup("setup.ini");
    setup.open(QIODevice::WriteOnly);
    QByteArray tmp(1, (char)language);
    setup.write(tmp, 1);
    setup.close();
    

    I already find this over-complicated. I mean I have to use a QByteArray, a cast to character, I have to say that I have 1 byte and for what? To get 8 bits out of it... In arduino I can simply use integers to write and read ezpz.

    I'd like to know how I can read a binary value from a text file and put the value in an integer.

    Thnx in advance.


  • Moderators

    Why not use QSettings? It's super simple, supports .ini and can store virtually any variable type.

    QSettings settings;
    settings.setValue("language", "En");
    //...
    QString language = settings.value("language");
    if (language == "En") {
      // do something
    }
    

    And if you really want to use a QFile directly:

    // Write:
    QFile file("myFile.ini");
    if (file.open(QFile::Text | QFile::WriteOnly) {
      file.write("En");
    }
    
    // Read:
    QFile file("myFile.ini");
    if (file.open(QFile::Text | QFile::ReadOnly) {
      QString language = file.readAll();
      if (language == "En") {
        // do something
      }
    }
    

    I mean I have to use a QByteArray, a cast to character, I have to say that I have 1 byte and for what?

    Please, relax. Qt is quite simple to use, but you need to approach with "I want to learn" attitude, and not expect it to work same as on Arduino. Qt is much more complex.


  • Moderators

    To add to @sierdzio, there is also QTextStream, QDataStream. Another thing: There is not necessarily the need to call close(), as the file is automatically closed when your setup object goes out of scope. And better don't use legacy C typecasts in new code.



  • @sierdzio said in Read a byte from a .txt and store it as it is in an integer.:

    Why not use QSettings? It's super simple, supports .ini and can store virtually any variable type.

    Because I did not know of it's existance. If somebody's code is not working, the answer to the question "why do you do..." is always "trying to get it to work" and the answer to the question "why don't you do..." is "Because I don't know"

    QSettings settings;
    settings.setValue("language", "En");
    //...
    QString language = settings.value("language");
    if (language == "En") {
      // do something
    }
    

    Thank you alot. I will try this out. It seems very promising.

    And if you really want to use a QFile directly:

    // Write:
    QFile file("myFile.ini");
    if (file.open(QFile::Text | QFile::WriteOnly) {
      file.write("En");
    }
    
    // Read:
    QFile file("myFile.ini");
    if (file.open(QFile::Text | QFile::ReadOnly) {
      QString language = file.readAll();
      if (language == "En") {
        // do something
      }
    }
    

    My good sir! I challenge you to use these functions with integers.

    Please, relax. Qt is quite simple to use, but you need to approach with "I want to learn" attitude, and not expect it to work same as on Arduino. Qt is much more complex.

    That I call Qt over-complicated does not mean I am not relaxed ;) And there is a difference between complex and overcomplicated sometimes. You should know how much misery I suffered when I wanted to read out 1 byte out of the serial port every 2ms. This was because the readyRead signal has a tendency to wait 2-3ms for follow-up bytes. A feauture good for reading IP packets, and a complete bug to my application.

    @Wieland said in Read a byte from a .txt and store it as it is in an integer.:

    To add to @sierdzio, there is also QTextStream, QDataStream. And better don't use legacy C typecasts in new code.

    QTextStream I already tried. I use it alot to store bytes in a text file. I tried getting the byte out with

    QFile setup("setup.ini");
      setup.open(QIODevice::ReadOnly);
      QTextStream tmp(&setup);
      tmp >> language;
      setup.close();
    

    According to this example-less webpage it should work. But there is one of those reference & thingies mentioned in the qt doc and I don't know what to do with it.

    'language' is an uint8_t. And my error message is:

    /home/user/GUI_Qt/mainwindow.cpp:154: error: no match for ‘operator>>’ (operand types are ‘QTextStream’ and ‘uint8_t {aka unsigned char}’)
       tmp >> language;
           ^
    

    So what I am doing wrong? language is an uint8_t.

    Another thing: There is not necessarily the need to call close(), as the file is automatically closed when your setup object goes out of scope

    Thank you, I did not know that.

    And better don't use legacy C typecasts in new code.

    Statements like this need explanations. I use typecasts sometimes and they work, they keep the compiler happy. So if you don't want people to use typecasts you need to toss them a bone, because I am not really in the mood to change my perfectly fine working code if I don't know 'why', you see?

    EDIT:
    I am not understanding how I can use QSettings. It seems to works with QStrings and I want to read out an integer.
    I think that solving the QTextStream issue is the quickest solution.


  • Moderators

    @bask185 said in Read a byte from a .txt and store it as it is in an integer.:

    So if you don't want people to use typecasts you need to toss them a bone, because I am not really in the mood to change my perfectly fine working code if I don't know 'why', you see?

    Actually it's basic C++ know-how.



  • This works!!! I forgot to use to use the .toInt();

    QSettings settings("setup");
     language = settings.value("setup").toInt();
     qDebug() << "language = set at "<< language;
    
    QSettings settings("setup");
    settings.setValue("setup", language);
    qDebug() << "language index =" << language;
    

    @Wieland said in Read a byte from a .txt and store it as it is in an integer.:

    @bask185 said in Read a byte from a .txt and store it as it is in an integer.:

    So if you don't want people to use typecasts you need to toss them a bone, because I am not really in the mood to change my perfectly fine working code if I don't know 'why', you see?

    Actually it's basic C++ know-how.

    So can you enlighten me and explain why my working typecasts shouldn't be used?


  • Moderators

    Just for the record, here's an example with QDataStream:

    int simpleWriteToFile(int value)
    {
        QFile file("language.bin");
        if (!file.open(QIODevice::WriteOnly))
            return -1;
        QDataStream ds(&file);
        ds << value;
        return 0;
    }
    
    int simpleReadFromFile(int &value)
    {
        QFile file("language.bin");
        if (!file.open(QIODevice::ReadOnly))
            return -1;
        QDataStream ds(&file);
        ds >> value;
        return 0;
    }
    

  • Moderators

    As another sidenote, there is QLocale which contains enum QLocale::Language and many utility functions. All for the sake of typesafety and platform independence.

    So can you enlighten me and explain why my working typecasts shouldn't be used?

    Because with C++ casts the compiler can find more of your bugs.



  • QFile file("language.bin");
    if (!file.open(QIODevice::ReadOnly))
        return -1;
    QDataStream ds(&file);
    ds >> value;
    return 0;
    
    QFile setup("setup.ini");
      setup.open(QIODevice::ReadOnly);
      QTextStream tmp(&setup);
      tmp >> language;
      setup.close();
    

    Why was mine not working, is that because of a difference between text- & datastream?? With exception of the if statement, the only difference in our codes is text- vs datastream


  • Moderators

    If you replace QDataStream with QTextStream, it will work, too. Don't know why your code didn't work, must have been some other problem. Only difference is, QDataStream will write your data with QDataStream's own platform independent binary serialization protocol. QTextStream will convert your integer to a character stream (UTF-8 by default).


  • Moderators

    @bask185 said in Read a byte from a .txt and store it as it is in an integer.:

    This works!!!

    Congrats!

    So can you enlighten me and explain why my working typecasts shouldn't be used?

    Mainly to develop good habits.

    In C++, there are several different categories of casts. C-style typecasts are the most flexible of them all, but also the most dangerous. C-style casts can cause the compiler to ignore buggy code, whereas a more restrictive cast will alert the programmer about the bug. It is good to understand the purposes of the different casts and choose the appropriate one for the task, instead of picking the same option every time.

    Here is a comprehensive description of each type of cast: https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used

    But in any case, there is often a solution which doesn't require a cast, yet is not over-complicated. Your case was no exception.

    @bask185 said in Read a byte from a .txt and store it as it is in an integer.:

    I have the storing part working but the reading part seems to be impossible.
    QFile setup("setup.ini");
    setup.open(QIODevice::WriteOnly);
    QByteArray tmp(1, (char)language);
    setup.write(tmp, 1);
    setup.close();

    I already find this over-complicated. I mean I have to use a QByteArray, a cast to character, I have to say that I have 1 byte and for what?

    There was no need to cast or to say you have 1 byte. Here is the equivalent of your original code:

    QFile setup("setup.ini");
    setup.open(QIODevice::WriteOnly); // TODO: Check that the opening succeeded
    setup.write(QByteArray::number(language));
    

    I'd like to know how I can read a binary value from a text file and put the value in an integer.

    For completeness, here's the "reverse" of the write-code:

    QFile setup("setup.ini");
    setup.open(QIODevice::ReadOnly); // TODO: Check that the opening succeeded
    int language = setup.readAll().toInt();
    

    NOTE: I still recommend the QSettings approach, because its intent is much clearer (in other words, the code is more readable). It also allows your program to grow in the future, in case you want to store more settings.
    NOTE: I also recommend doing the run-time check, if (!setup.open(...)) {/*Handle error*/}, like what @sierdzio and @Wieland did in their code. This too, is a good habit.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.