2017-08-08 2 views
0

Dies ist eine QT-Frage zur Verwendung von QDataStream und QTemporaryFile in C++ und Linux.QDataStream und Flush

Ich habe einige Probleme bekommen einen QDataStream zu spülen. QTextStream hat eine Flush-Funktion, QDataStream benötigt jedoch anscheinend keine. (Zitat von 2013: http://www.qtcentre.org/threads/53042-QDataStream-and-flush()). Meine Frage ist, ist das tatsächlich/immer noch der Fall, und gibt es sowieso einen QDataStream zu erzwingen?

Wenn ich die Datei, die ich mit QDataStream geschrieben habe, verarbeite, fehlt die letzte Anzahl von Schreibvorgängen (112 Bytes beim Schreiben von 5 Bytes, 22 Bytes beim Schreiben von 1 Byte gleichzeitig). Wenn ich jedoch eine große Menge Padding an das Ende der Datei schreibe, dann ist der gesamte Inhalt vorhanden (mit Ausnahme der letzten paar Schreibvorgänge der Auffüllung). Deshalb glaube ich, dass der QDataStream nicht in die Datei geleert wird.

Die Dateien, die ich verarbeite, sind mittelgroße rohe Binärdateien (etwa 2 MB).

hier ein minimales Beispiel einen Teil des Codes mit I für die Verarbeitung der Dateien haben:

void read_and_process_file(QString &filename) { 
    QFile inputFile(filename); 
    if (!inputFile.open(QIODevice::ReadOnly)) { 
    qDebug() << "Couldn't open: " << filename; 
    return; 
    } 
    QDataStream fstream(&inputFile); 
    QTemporaryFile *tempfile = new QTemporaryFile(); 
    if (!tempfile->open()) { 
    qDebug() << "Couldn't open tempfile"; 
    return; 
    } 
    QDataStream ostream(tempfile); 

    while (!fstream.atEnd()) { 
    int block_size = 5;  //The number to read at a time 
    char lines[block_size]; 

    //Read from the input file 
    int len = fstream.readRawData(lines,block_size); 
    QByteArray data(lines,len); 

    //Will process data here once copying works 

    //Write to the temporary file 
    ostream.writeRawData(data,data.size()); 
    } 
    process_file(tempfile); 
    delete tempfile; 
} 
+1

Versuchen Sie 'tempfile-> close()' aufzurufen, bevor Sie 'process_file (tempfile)' aufrufen. – hank

+0

Hank, das scheint das Problem zu entfernen, danke. Besteht nicht die Möglichkeit, dass die temporäre Datei aufgeräumt wird, wenn sie geschlossen ist? Ich werde einige Tests durchführen und das überprüfen. –

+1

Nein, 'QTemporaryFile :: close' löscht die Datei nicht. Die Datei wird gelöscht, wenn das 'QTemporaryFile'-Objekt zerstört wird. Außerdem würde ich vorschlagen, Objekte nicht in einem einzigen Bereich unter Verwendung von "neu" zuzuweisen, da dies zu Speicherlecks führen kann. In Ihrem Beispiel erhalten Sie ein Leck nach "Temp Datei konnte nicht geöffnet werden". Ordnen Sie Ihr Objekt einfach dem Stack zu: 'QTemporaryFile tempfile;' – hank

Antwort

2

Der erste Teil dieser Antwort ist unabhängig von der Frage der die Datei auf die Festplatte spülen.


Verwendung von !fstream.atEnd() als bedingten von while ist keine gute Idee. Siehe http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong. Ich würde die while Schleife ändern:

const int block_size = 5;  //The number to read at a time 
char lines[block_size]; 
int len = 0; 
while ((len = fstream.readRawData(lines,block_size)) > 0) { 

    QByteArray data(lines, len); 

    //Will process data here once copying works 

    //Write to the temporary file 
    ostream.writeRawData(data,data.size()); 
} 

Aber ich sehe nicht den Punkt der Zwischen QByteArray verwenden. Das Schleife vereinfacht werden kann:

while ((len = fstream.readRawData(lines,block_size)) > 0) { 
    //Write to the temporary file 
    ostream.writeRawData(lines, len); 
} 

Wenn Sie die QByteArray für andere Dinge verarbeiten müssen, ist es in Ordnung einen zu bauen und es verwenden, aber der Aufruf von ostream.writeRawData braucht nicht, es zu benutzen.


Re. Das Problem, dass die Datei nicht gelöscht wird, würde ich vorschlagen, einen verschachtelten Bereich zu verwenden, um die Datei zu öffnen. Die Datei sollte am Ende des Bereichs geleert und geschlossen werden.

void read_and_process_file(QString &filename) { 

    QFile inputFile(filename); 
    if (!inputFile.open(QIODevice::ReadOnly)) { 
     qDebug() << "Couldn't open: " << filename; 
     return; 
    } 

    QDataStream fstream(&inputFile); 
    QTemporaryFile *tempfile = new QTemporaryFile(); 
    if (!tempfile->open()) { 
     qDebug() << "Couldn't open tempfile"; 
     return; 
    } 

    // Create a nested scope for the QDataStream 
    // object so it gets flushed and closed when the 
    // scope ends. 
    { 
     QDataStream ostream(tempfile); 

     const int block_size = 5;  //The number to read at a time 
     char lines[block_size]; 
     int len = 0; 
     while ((len = fstream.readRawData(lines,block_size)) > 0) { 

     QByteArray data(lines, len); 

     //Will process data here once copying works 

     //Write to the temporary file 
     ostream.writeRawData(lines, len); 
     } 

     // The QDataStream should be flushed and 
     // closed at the end of this scope. 
    } 

    process_file(tempfile); 
    delete tempfile; 
} 
+0

Danke, guter Vorschlag. Ich habe die Schleife nur dann auf Ende gesetzt, wenn len <= 0, wie der ursprüngliche Kommentar vorgeschlagen hat. Und Sie haben Recht, das QByteArray wird für ein minimales Beispiel nicht benötigt. Leider ist dies zwar hilfreich, löst das Problem jedoch nicht. –

+0

@Weir_Doe, siehe das Update. –