Zeilen in Textfile sortieren und doppelte löschen

Alles rund um die Programmierung mit Qt
Antworten
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Zeilen in Textfile sortieren und doppelte löschen

Beitrag von freakonaleash99 »

Hallo zusammen,
ich habe mir ein Programm gebastelt, um aus vielen Textdateien jeweils die doppelten Zeilen zu löschen und die Zeilen dann noch sortiert werden.
Das Problem ist, dass die Ausführung relativ lange dauert. Es handelt sich um bis zu etwa 150-200 einzelne Dateien, jeweils so ca. 150kb groß.
Meine Frage zu dem bestehenden Code ist, ob es eine Möglichkeit gibt, die Ausführung zu beschleunigen, also den Code effizienter gestalten kann. Wenn ja, wäre ich dankbar für Tips.
Im Folgenden mein Code:

Code: Alles auswählen


    QString WorkFolder = "C:/workfolder/";
    QStringList FileContent;
    bool line_exists=false;
 
    QDirIterator it_doppel(WorkFolder, QStringList() << "*.txt", QDir::Files, QDirIterator::Subdirectories);
    while (it_doppel.hasNext()) {
        FileList << it_doppel.next();
    }
 
 
    for(int i = 0; i < FileList.size(); i++){
        QFile filein(FileList[i]);
        if (!filein.open(QIODevice::ReadOnly | QIODevice::Text))
            return;
 
        while (!filein.atEnd()) {
            QByteArray line = filein.readLine();
            QString str_line = line;
            for(int x = 0; x < FileContent.size(); ++x){
                if(FileContent[x] == str_line){
                    line_exists=true;
                    break;
                }
            }
            if(line_exists == false){
                FileContent << str_line;
            }
 
            line_exists=false;
 
        }
 
 
        QFile fileout(FileList[i]);
        if (!fileout.open(QIODevice::WriteOnly | QIODevice::Text))
            return;
 
        FileContent.sort();
 
        QTextStream out(&fileout);
        for(int y = 0; y < FileContent.size(); ++y){
            out << FileContent[y];
        }
 
        FileContent.clear();
    }
 
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von Christian81 »

Anstatt jede Zeile in einem QVector zu vergleichen was eine O² Komplexität erzeugt, bietet sich ggf. ein QSet<QByteArray> an - dort sollte der Lookup wesentlicher schneller sein. Siehe auch http://doc.qt.io/qt-5/containers.html#a ... complexity
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von freakonaleash99 »

Vielen Dank. Werde mir die Doku bei Gelegenheit in Ruhe durchlesen.
Habe erstmal die schnelle Variante gewählt und "QStringList FileContent" durch "QSet<QByteArray> FileContent" ersetzt und nachfolgenden Code natürlich entsprechend angepasst. Schein auch zu funktionieren, gefühlt auch etwas schneller. Allerdings musste ich die Sortierung erstmal rausnehmen. Und genau da scheitere ich momentan. Ich schaffe es nicht, das Set richtig zu sortieren (alphabetisch bzw. Zahlen aufwärts).
Habe es mit dem Ansatz qSort(FileContent) versucht. Hat allerdings nicht funktioniert. Ich vermute, dass ich das ganze Set doch wieder in QStrings umwandeln muss?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von Christian81 »

Ein QSet kann man nicht sortieren - das per Definition ein Hash-Table und sowas ist nunmal nicht sortiert.
Nach dem Einlesen alles von einem QSet in ein QVector<QBytrArray> konvertieren, dann qSort (ggf. mit einer eigenen Sortierfunktion) drüber und gut ist.Konvertieren von/nach QString würde ich vermeiden wenn es geht, deshalb ist QTextStream auch die schlechteste Wahl - ein QFile::write() inklusive "\n" reicht vollkommen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von freakonaleash99 »

Danke nochmals. Sortierung funktionier perfekt.

Aber so 100% gehts es dann doch noch nicht. Wollte es zunächst mal test und folgende code dazu geschrieben:

Code: Alles auswählen

    QSet<QByteArray> Test;
    QVector<QByteArray> Test2;

    Test<< "Test" << "Hallo" << "Name" << "123" << "004" << "110";

    foreach (const QByteArray &value, Test){
        //qDebug() << value;
        Test2 << value;
    }

    qSort(Test2);

   QFile file("C:/workfolder/Testdokument.txt");

        file.open(QIODevice::WriteOnly);
        foreach (const QByteArray &value3, Test2){
          qDebug()<<value3;
          file.write(value3);
        }


Dazu mehrere Frage:
1. Konvertierung von Qset nach QVector geht nur über Iteration der einzelnen Einträge, oder? (also so wie ich es oben gemacht habe, bzw. zumindest nach diesem Prinzip)
2. Leider werden die Daten nicht in das Dokument geschrieben, es bleibt komplett leer. Habe auch QIODevice::Append versucht, weil ich nicht sicher war.
Könnte es auch mit nem DataStream versuchen, allerdings weiß ich auch nicht, ob das unbedingt besser ist als der TextStream...
Finde für write() nichts in der Doku.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von Christian81 »

1. ja, so in der Art, was anderes geht nicht
2. Den Rückgabewert von QFile::open() mal überprüft?
Und QDataStream ist definitiv nicht das, was Du suchst ...

/edit: das nicht hinzugefügt... sorry
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von freakonaleash99 »

Ok vielen Dank.
Ja Datei wird richtig geöffnet.
Mit QDataStream sollte es klappen.
Ich dachte nur, dass es eine noch bessere Lösung nur mit "Write()" gibt.
Danke für dein Hilfe, werde morgen meinen kompletten code nochmal posten, damit alle was davon habe ;)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von Christian81 »

Oh, mein Fehler. Da fehlt ein 'nicht' ...
Und QDataStream ist definitiv nicht das, was Du suchst ...

QDataStream gibt es als Daten aus, eine Qt-interne Repräsentation ... damit kannst Du nichts anfangen.

Versuche mal irgendwas in die Datei zu schreiben (und vergiss QFile::close() nicht) - das sollte klappen. Wenn nicht -> minimales Beispiel bitte.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von freakonaleash99 »

Bzgl. QDataStream habe ich heute gemerkt was passiert :D
mit file.write() funktioniert es jetzt doch. Warum weiß ich noch nicht so genau.

hier das funktionierende Beispiel:

Code: Alles auswählen

    QSet<QByteArray> Test;
    QVector<QByteArray> Test2;

    Test<< "Test" << "Hallo" << "Name" << "123" << "004" << "110";

    foreach (const QByteArray &value, Test){
        //qDebug() << value;
        Test2 << value;
    }

    qSort(Test2);

   QFile file("C:/Workfolder/Testdokument.txt");

        file.open(QIODevice::WriteOnly);
        foreach (const QByteArray &value3, Test2){
          file.write(value3+"\n");

        }
        file.close();
habs noch nicht in das eigentlich Programm eingebaut. Werde ich die Tage mal versuchen und die Laufzeiten vergleichen.
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von freakonaleash99 »

Also es ist tatsächlich deutlich schneller geworden als vorher. Vielen Dank dafür!

Trotzdem gibt es noch ein gewisse Zeit, in der das Programm "nicht reagiert". Ich denke, dass es aber einfach der Menge an Dateien zu verschulden ist.
Daher noch eine weitere Frage:
Gibt es eine Möglichkeit, sich den Fortschritt irgendwie anzeigen zu lassen, oder zumindest ein Feld, in dem dann steht, dass das Programm am arbeiten ist?
Habe es über eine QLabel versucht: Hab und die Funktion, die zum löschen der doppelten Zeile aufgerufen wird, am Anfang und am Ende eingebaut, dass der Text des QLabels am Anfang auf "Working..." gesetzt wird und am Ende "Ready" oder sowas ähnliches.
Leider wird das Label nicht auf "Working" gesetzt, das Programm fängt anscheinend schneller mit dem sortieren und löschen an als es das Label setzen kann...

Wie gehe ich da am besten vor?
Alternativ könnte ich mir auch ein TextBrowser vorstellen, in dem die aktuell bearbeiteten Dateien aufgelistet werden. Allerdings wird auch dieser nicht aktualisiert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Zeilen in Textfile sortieren und doppelte löschen

Beitrag von Christian81 »

Man könnte den Cursor in einen WaitCursor setzen
Man könnte eine QProgressBar(Dialog) laufen lassen (muss man natürlich zyklisch mal aufrufen - siehe http://doc.qt.io/qt-5/qprogressdialog.html#details )
Man könnte die ganze Verarbeitung in einen Thread auslagern, ist aber meiner Meinung nach nicht unbedingt etwas für Anfänger.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten