Results 1 to 15 of 15

Thread: Reading and rereading a file with QXmlStreamReader

  1. #1
    Join Date
    Jun 2006
    Location
    Sweden
    Posts
    99
    Thanks
    11
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Reading and rereading a file with QXmlStreamReader

    My fellow Qt enthusiasts,

    I have a parser class that inherits QXmlStreamReader. The class is supposed to do two things: 1) parse the contents of the file. 2) determine the 'type' of xml file (getType(..) ).

    I would like for the getType()-method to read only as far into the file as necessary before returning with the type. That is to say, i want to read as little as possible of the file to determine its type.

    The problem is that after returning the type and aborting the read, the subsequent attempt to read the entire file fails with "premature end of document". I have tried using QXmlStreamReader::clear(), i've tried QIODevice::reset(), QIODevice::seek(0), none of them manage to reset the device properly. QIODevice::pos() returns 0 after each of the above operations and yet it does not seem to be properly reset.

    If i create two instances of Parser, and let one do getType and the other parse the IODevice, then it works. But it's a cheap victory since it's not behaving the way i want. What am i doing wrong?

    Example:

    I have two types of xml-files, each identifiable by the root-tag:

    <typeA>
    ...
    </typeA>

    and

    <typeB>
    ...
    </typeB>

    My getType() method looks something like this:

    Qt Code:
    1. FileType Parser::getType(QIODevice* device)
    2. {
    3. setDevice(device);
    4. while (!atEnd()){
    5. readNext();
    6.  
    7. if (isStartElement()){
    8. if (name() == "typeA"){
    9. return TypeA;
    10. }else if (name() == "typeB"){
    11. return TypeB;
    12. }else{
    13. return UnknownType;
    14. }
    15. }
    16. }
    17.  
    18. return UnknownType;
    19.  
    20. }
    To copy to clipboard, switch view to plain text mode 

    My read()-method is simple:
    Qt Code:
    1. bool Parser::read(QIODevice* device)
    2. {
    3. setDevice(device);
    4. while (!atEnd()){
    5. readNext();
    6.  
    7. cout << "token: " << tokenString().toStdString() << endl;
    8.  
    9. }
    10. return !error();
    11. }
    To copy to clipboard, switch view to plain text mode 

    My calling method looks like this:

    Qt Code:
    1. QFile file(fileName);
    2. if (!file.open(QFile::ReadOnly | QFile::Text)){
    3. cout << "error" << endl;
    4. return;
    5. }
    6.  
    7. Parser reader;
    8. FileType type = reader.getType(&file);
    9. if (type == TypeA){
    10. reader.read(&file);
    11. }
    12.  
    13. file.close();
    To copy to clipboard, switch view to plain text mode 

    As always, thanks in advance!

  2. #2
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Reading and rereading a file with QXmlStreamReader

    Not sure if you are supposed to derive a class from QXmlStreamReader. None of the methods in QXmlStreamReader are virtual, not even the destructor...

  3. #3
    Join Date
    Jan 2008
    Location
    Poland
    Posts
    687
    Thanks
    4
    Thanked 140 Times in 132 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by lni View Post
    Not sure if you are supposed to derive a class from QXmlStreamReader. None of the methods in QXmlStreamReader are virtual, not even the destructor...
    It doesn't matter as typically you are subclassing QXmlStreamReader to make your own reader supposed to read your own specific XML files, ao you add some methods which use QXmlStreamReader's methods.

    What happens when you close() and open() file again?
    What about saving file data to QByteArray (with readAll()) and use parser on it instead of on file?

    I'm just guessing :]
    I would like to be a "Guru"

    Useful hints (try them before asking):
    1. Use Qt Assistant
    2. Search the forum

    If you haven't found solution yet then create new topic with smart question.

  4. #4
    Join Date
    Jun 2006
    Location
    Sweden
    Posts
    99
    Thanks
    11
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by lni View Post
    Not sure if you are supposed to derive a class from QXmlStreamReader. None of the methods in QXmlStreamReader are virtual, not even the destructor...
    In Java-speak, i'm doing Extends, not Implements. So there needn't be any virtual methods.

    faldżip:

    Closing and reopening the file had, strangely enough, no effect. I'm thinking it's the StreamReader that doesn't reset-itself properly, even after calling clear() and resetting the device.

    I'm sure i could do a readAll as you suggested but my goal was to read as little of the file as possible to save time on I/O and memory. Right now i'm throwing the first reader away and creating a new one when i want to read the entire file, but it doesn't feel like the best solution.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading and rereading a file with QXmlStreamReader

    Why reset the file at all? Can't you continue reading from the place where you stopped?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by faldżip View Post
    It doesn't matter as typically you are subclassing QXmlStreamReader to make your own reader supposed to read your own specific XML files, ao you add some methods which use QXmlStreamReader's methods.
    What I have done is by following qt designer, by making various Dom objects and let QXmlStreamReader/QXmlStreamWriter read/write the data.

    I don't think Qt people would make such mistake by not even providing a virtual destructor if they think people could use it as a based class, of course C++ doesn't stop people from doing it...unlike the keyword "final" in java...

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by lni View Post
    I don't think Qt people would make such mistake by not even providing a virtual destructor if they think people could use it as a based class, of course C++ doesn't stop people from doing it...unlike the keyword "final" in java...
    Correct me if I'm wrong but virtual destructor is needed only if you have some other methods declared as virtual. Lack of virtual methods doesn't prevent you from adding new methods.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by wysota View Post
    Correct me if I'm wrong but virtual destructor is needed only if you have some other methods declared as virtual. Lack of virtual methods doesn't prevent you from adding new methods.
    virtual destructor is necessary if the class is intended to be a based class regardless the class itself has virtual methods or not. Otherwise they could be memory leak.

    For instance, in the following code, B's dtor will not be called because A's dtor is not virtual. If you make A's dtor virtual, then the memory will be properly freed.

    In java, you could add "final" keyword so no one can derive from A, but in C++ there is no such keyword...I guess this is one of C++'s weakness...


    Qt Code:
    1. #include <iostream>
    2.  
    3. class A {
    4. public:
    5. ~A() {
    6. std::cout << "A::~A called" << std::endl;
    7. }
    8.  
    9. };
    10.  
    11. class B : public A {
    12. public:
    13.  
    14. ~B() {
    15. std::cout << "B::~B called" << std::endl;
    16. }
    17.  
    18. };
    19.  
    20. int main()
    21. {
    22. A* a = new B;
    23. delete a;
    24.  
    25. }
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading and rereading a file with QXmlStreamReader

    Who said you had to use the class this way? If you cast the object to the base class then you have a point in doing so - you expect some method to be virtual. If you just use the object of the subclass as an extension of the superclass then both destructors will be called. If you have a stack-based object (and we're dealing with one here) then everything will be alright.

    Qt Code:
    1. int main(){
    2. B b;
    3. return 0;
    4. }
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Jun 2006
    Location
    Sweden
    Posts
    99
    Thanks
    11
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by wysota View Post
    Why reset the file at all? Can't you continue reading from the place where you stopped?
    I'm not sure i can since i get the "unexpected end of file"-error when i don't reset. The same is true even if i reset the file or close and reopen it. The only way around this i've found is to create a new streamReader-derived object AND reset the QIODevice:

    Qt Code:
    1. QFile file(fileName);
    2. file.open(QFile::ReadOnly | QFile::Text);
    3.  
    4. Parser typeCheck; // type checker!
    5. FileType type = typeCheck.getType(&file);
    6. file.reset();
    7. if (type == TypeA){
    8. Parser reader; // actual reading of the file
    9. if (!reader.read(&file)){
    10. cout << "uh oh." << endl;
    11. }
    12. }else{
    13. cout << "bad file type." << endl;
    14. }
    15. file.close();
    To copy to clipboard, switch view to plain text mode 

    Correct me if i'm wrong but this feels like a bug. According to the documentation, QXmlStreamReader::setDevice() is supposed to reset the reader's internal state. If that were true, then doing reset() on the IODevice and resetting the reader's device should work.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by TheRonin View Post
    I'm not sure i can since i get the "unexpected end of file"-error when i don't reset.
    Because you try reading from the beginning. You have to continue reading where you left off (after determining the internal type of the file).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #12
    Join Date
    Feb 2009
    Location
    Noida, India
    Posts
    517
    Thanks
    21
    Thanked 66 Times in 62 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by lni View Post
    In java, you could add "final" keyword so no one can derive from A, but in C++ there is no such keyword...I guess this is one of C++'s weakness...
    if you keep a destructor of a class as private, most compilers would not let that class be subclassed..at least thats how Stroustrup intended it, some compilers seem to have ignored that..but all GNU compilers would not let you subclass a class with private destructor..so its no weakness of C++..anything that java can do, c++ can do it on one leg with high heels..with less memory consumption

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by talk2amulya View Post
    anything that java can do, c++ can do it on one leg with high heels..with less memory consumption
    Except for proper exception handling
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #14
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Reading and rereading a file with QXmlStreamReader

    Quote Originally Posted by talk2amulya View Post
    if you keep a destructor of a class as private, most compilers would not let that class be subclassed..at least thats how Stroustrup intended it, some compilers seem to have ignored that..but all GNU compilers would not let you subclass a class with private destructor..so its no weakness of C++..anything that java can do, c++ can do it on one leg with high heels..with less memory consumption
    How do you delete the object if the dtor is private? You will have to provide a public "release" method to call when you want to delete it, and you won't be able to create an object on stack with private dtor...

    For a class without virtual dtor, the object will have no vtable, you won't gain anything to use "IsA" relationship. I would use "hasA" relationship to be more intuitive and avoid possible memory leak. Again, C++ don't stop you from deriving from it....

  15. #15
    Join Date
    Apr 2015
    Posts
    1
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Reading and rereading a file with QXmlStreamReader

    Qt Code:
    1. void QXmlStreamReader::setDevice(QIODevice * device)
    To copy to clipboard, switch view to plain text mode 

    Sets the current device to device. Setting the device resets the stream to its initial state.

    See also device() and clear().
    http://doc.qt.io/qt-4.8/qxmlstreamre...l#namespaceUri

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.