Neue Textfiles automatisch erkennen & verarbeiten



  • Hallo zusammen 🙂

    mir ist hier schon mal so super geholfen, dass ich direkt noch mal Rat suchen muss 🙄

    Ich hab ein Programm, dass Dateien konvertiert. Jetzt ist es so, dass ca. jede Minute eine neue Ursprungsdatei generiert wird. Ist es möglich, dass mein Programm automatisch erkennt, dass eine neue Datei in dem angegebenen Order hinzugekommen ist?
    Also dass ich den Ordner angebe, dass Programm schläft bis eine neue Datei im Ordner erscheint, Programm konvertiert die Daten und schläft bis zur nächsten neuen Datei.

    Irgendwie konnte ne Googlesuche mir dabei nicht weiterhelfen... Hab leider keine Ahnung ob und wie das wenn überhaupt möglich ist...

    Bin für jeden Tipp und Ratschlag super dankbar! 🙂


  • Mod

    Ist es möglich, dass mein Programm automatisch erkennt, dass eine neue Datei in dem angegebenen Order hinzugekommen ist?

    Ja, aber nicht mit der C++-Standardbibliothek. Dafür kannst du die WinAPI verwenden, oder aber auch Boost.Filesystem.



  • Ist betriebssystemabhämgig und geht vermutlich. Welches haste? Linux, Windows, .NET?



  • Da gibt´s zwei Ansätze:

    1. du benutzt OS-spezifische Funktionen, unter Win32 gibt es z.b. ReadDirectoryChangesW, das u.A. Verzeichnisse überwachen kann.

    2. du liest zu Programmstart alle Dateinamen in einen vektor und prüfst zyklisch, ob eine neue Datei hinzugekommen ist. Könnte mit der Zeit etwas träge werden, wenn sich sehr viele Dateien im Ordner sammeln.

    Wie merkst du dir, ob eine Datei schon bearbeitet wurde? Darfst du sie löschen/verschieben oder setzt du ein Dateiflag?



  • Vielen Dank für die schnellen Antworten! 🙂

    Also ich arbeite mit Visual Studio 2010 auf nem Windows 7 Rechner. Was käme dann noch in Frage? Also für Windows 🙄

    Es werden immer nur ca. 50 Dateien im Ordner behalten. Also wenn ne neue Datei kommt fliegt die Älteste raus. Der Name der Datei ist einfach durchnummeriert, also wollte ich mir die Nr. der letzen Datei merken, die ich gelesen hab und anhand dessen Testen ob ne neue, mit größerer Nr. vorhanden ist.



  • Und was passiert, wenn dein Programm einige Zeit nicht läuft und in dieser Zeit neue Dateien hinzukommen? Wie unterscheidest du dann zu Programmstart, welche Dateien bereits behandelt worden sind?



  • Mit "Nr. der letzen Datei merken" ist ja vielleicht persistent merken gemeint.



  • Ich hatte gerade langeweile und habe mal schnell ein Beispiel abgetippt. Das einzige was du hier speichern musst ist die letzte ausführung deines Programms in time_t.

    #include <boost/filesystem.hpp>
    #include <string>
    #include <vector>
    #include <ctime>
    #include <chrono>
    
    std::vector< boost::filesystem::path > getFilesFromDirectory( const std::string& path )
    {
        boost::filesystem::path dir( path );
        std::vector< boost::filesystem::path > files;
    
        if( !boost::filesystem::is_directory( dir ) )
        {
            return files;
        }
    
        boost::filesystem::directory_iterator end;
        for( boost::filesystem::directory_iterator iter( path ); iter != end; ++iter )
        {
            if( boost::filesystem::is_regular_file( *iter ) )
            {
                files.push_back( *iter );
            }
        }
        return files;
    }
    
    bool isFileModifiedAfter( const boost::filesystem::path& path, const std::time_t& time )
    {
        std::time_t lastModified = boost::filesystem::last_write_time( path );
        return lastModified > time;
    }
    
    int main() try
    {
        auto files = getFilesFromDirectory( "/home/user/Pictures" );
    
        //beispeil: Programm wurde vor 24 Stunden das letzte mal ausgeführt
        std::chrono::time_point<std::chrono::system_clock> currentTime( std::chrono::system_clock::now() );
        std::time_t lastRuntime = std::chrono::system_clock::to_time_t( currentTime - std::chrono::hours(24) );
    
        for( auto iter : files )
        {
            if( isFileModifiedAfter( iter, lastRuntime ) )
            {
                std::cout << iter.string() << "\n";
            }
        }
    }
    catch(...)
    {
        std::cerr << "AUA!!!\n";
    }
    


  • Danke für das Beispiel! Ich werd es mal einbauen und ausprobieren 🙂

    Also wenn mein Programm länger als eine Stunde nicht gelaufen hat weiß ich sicher, dass alle Dateien, die sich zur Zeit im Ordner befinden noch nicht konvertiert wurden. Es ist so, dass die Dateien innerhalb einer Stunde alle ausgetauscht werden. Jede Minute kommt ja eine Neue, die eine Alte verdrängt und da nur ca. 50 im Ordner sein dürfen wird altes Zeug ruck zuck gelöscht. Nachdem die Dateien im Ordner erschienen sind werden die auch nicht mehr bearbeitet. Wenn die einmal konvertiert sind, sind die absolut nutzlos 😛


  • Mod

    boost::filesystem::directory_iterator end;
        for( boost::filesystem::directory_iterator iter( path ); iter != end; ++iter )
        {
            if( boost::filesystem::is_regular_file( *iter ) )
            {
                files.push_back( *iter );
            }
        }
    

    Wie wärs mit

    std::copy_if( boost::filesystem::directory_iterator(path), {}, std::back_inserter(files), boost::filesystem::is_regular_file);
    

    (ungetestet)?


  • Mod

    Wie wär's mit?

    template <typename OutputIterator>
    void getFilesFromDirectory( boost::filesystem::path path, OutputIterator out )
    {
        if( !boost::filesystem::is_directory( dir ) )
            throw std::domain_error{};
    
        std::copy_if( boost::filesystem::directory_iterator(path), {}, out, boost::filesystem::is_regular_file);
    }
    


  • Ich würde dabei auf #2 des Doktors setzen, leicht modifiziert

    DocShoe schrieb:

    1. du liest zu Programmstart alle Dateinamen in einen vektor und prüfst zyklisch, ob eine neue Datei hinzugekommen ist. Könnte mit der Zeit etwas träge werden, wenn sich sehr viele Dateien im Ordner sammeln.

    Modifikation: du holst dir eine Liste der Filenamen in dem Verzeichnis inklusive dem "last write" Datum zu jedem File.
    Dann holst du dir die selbe Liste für das Ausgabeverzeichnis, also das wo du die konvertierten Files reinlegst.
    Und dann suchst du in der ersten Liste nach (name, datum) Paaren die in der 2. Liste nicht vorkommen.

    Dadurch erkennst du wenn neue Files dazukommen, und auch wenn alte Files geändert werden.

    Die neuen bzw. geänderten Files konvertierst du dann, und nach dem Konvertieren setzt du das "last write" Datum des konvertierten Files auf das des Original-Files. Dadurch wird das File dann beim nächsten Durchlauf nicht als "geändert" erkannt.

    Bzw. falls du die Original-Files nach dem Konvertieren löscht oder in ein anderes Verzeichnis verschiebst, kannst du dir den Aufwand natürlich auch sparen 😉
    Dann müsstest du allerdings sowieso nur prüfen ob in dem Verzeichnis überhaupt irgendwelche Dateien drin sind, weil eh alles was da ist noch konvertiert werden muss.
    Was übrigens auch eine recht elegante Lösung wäre. Falls sich damit alle deine Anforderungen erfüllen lassen, würde ich darüber nachdenken ob es nicht besser wäre es so zu machen.





  • hustbaer schrieb:

    Bzw. falls du die Original-Files nach dem Konvertieren löscht oder in ein anderes Verzeichnis verschiebst, kannst du dir den Aufwand natürlich auch sparen 😉
    Dann müsstest du allerdings sowieso nur prüfen ob in dem Verzeichnis überhaupt irgendwelche Dateien drin sind, weil eh alles was da ist noch konvertiert werden muss.
    Was übrigens auch eine recht elegante Lösung wäre. Falls sich damit alle deine Anforderungen erfüllen lassen, würde ich darüber nachdenken ob es nicht besser wäre es so zu machen.

    Da die Dateien nach der Konvertierung

    antje schrieb:

    absolut nutzlos

    sind, würde ich es genau so machen.



  • Dann ist die Aufgabe ja echt trivial.
    Lässt sich mit einem Batch-File umsetzen.
    Been there, done that, got the T-shirt.


Anmelden zum Antworten