Wie den Dateityp bestimmen?



  • Hallo!

    ich habe eine Interfaceklasse:

    class File {
    
    public: 
    virtual bool Open(const std::string& pathToFile) = 0;
    };
    

    Davon erben jetzt meinetwegen FileCSV, FileAvi, FileXML usw. und implementieren die Open-Methode entsprechend. Jetzt wählt der Benutzer eine Datei auf der Festplatte aus, wie würde ich am elegantesten den Typ der Datei bestimmen, ohne dass der Benutzer etwas dafür machen muss. Nur die Endung anschauen finde ich schlecht.

    Meine Idee war sowas:

    File *pFile = new FileCSV();
    
    if(!pFile->Open(pathToFile)) {
         delete pFile;
         pFile = new FileAvi();
    
         if(!pFile->Open(pathToFile)) {
         // usw
    

    Wie macht man sowas normalerweise?


  • Mod

    Eine beliebige Art von Datei auf ihren Typ analysieren? Anhand des Inhalts natürlich. Die meisten Dateitypen haben recht eindeutig identifizierbare Header. Es ist also nur eine Fleißaufgabe diese Information aus aller Welt zusammenzutragen und jeweils einzeln zu prüfen. Oder du benutzt den Code vom Unix-Kommando file (ist schließlich freie quelloffene Software). Oder besser du benutzt gleich file 🙂 .



  • Ok, Nachtrag ;): Es soll keine beliebige Datei sein, sondern eine der 7 für die die Klasse implementiert wurde. Das kann dann auch ein Eigenformat sein. Und XML-Dateien haben z.B. auch keinen Header im eigentlichen Sinne


  • Mod

    Filermaster schrieb:

    Ok, Nachtrag ;): Es soll keine beliebige Datei sein, sondern eine der 7 für die die Klasse implementiert wurde. Das kann dann auch ein Eigenformat sein. Und XML-Dateien haben z.B. auch keinen Header im eigentlichen Sinne

    Trotzdem kann man als Mensch XML-Dateien ziemlich eindeutig erkennen, oder? Das bekommt ein Computer erst recht hin.

    Aber wenn du dich nicht auf Endungen verlassen willst, dann musst du dich zwangsläufig irgendwie am Inhalt orientieren. Irgendeinen Unterschied muss es zwischen den Dateiformaten ja geben (sonst wären sie ja gleich) und wenn man diesen in Worte fassen kann, dann kann man auch eine Überprüfung programmieren. Es sei denn es handelt sich bei allem um header- und strukturlose Binärdaten, deren Interpretation rein durch den Kontext des öffnenden Programms erfolgt. In diesem Fall wärst du aufgeschmissen.



  • SeppJ schrieb:

    Filermaster schrieb:

    Ok, Nachtrag ;): Es soll keine beliebige Datei sein, sondern eine der 7 für die die Klasse implementiert wurde. Das kann dann auch ein Eigenformat sein. Und XML-Dateien haben z.B. auch keinen Header im eigentlichen Sinne

    Trotzdem kann man als Mensch XML-Dateien ziemlich eindeutig erkennen, oder? Das bekommt ein Computer erst recht hin.

    Aber wenn du dich nicht auf Endungen verlassen willst, dann musst du dich zwangsläufig irgendwie am Inhalt orientieren. Irgendeinen Unterschied muss es zwischen den Dateiformaten ja geben (sonst wären sie ja gleich) und wenn man diesen in Worte fassen kann, dann kann man auch eine Überprüfung programmieren. Es sei denn es handelt sich bei allem um header- und strukturlose Binärdaten, deren Interpretation rein durch den Kontext des öffnenden Programms erfolgt. In diesem Fall wärst du aufgeschmissen.

    Darauf zielt ja meine Frage ab. Angenommen der Benutzer will eine *.doc Datei mit meinem Programm öffnen und ich unterstütze xls, xml, avi, doc.
    Dann würde ich wie im Eingangspost beschrieben solange ein neues Objekt vom Typ "File" anlegen, bis eine der Open-Methoden "true" zurückliefert, also den Inhalt lesen kann.

    Meine Frage war, ob das besser geht oder schon OK so ist



  • Ich finds blöd.

    Wenn du sieben Typen unterstützt, kann es dem Nutzer passieren, dass die Datei siebenmal geöffnet und analysiert werden muss. Das dauert doch nur unnötig lange. Was hast du denn gegen Dateiendungen? Über diese könntest du zumindest den ersten Kandidaten auswählen, mit dem du die Datei öffnen willst.



  • Wenn es über Dateiendungen geht, kannst du ganz simpel pro File-Derivat eine Factory-Methode in einer std::map<std::string, factoryMethod> registrieren, wobei die Endung der key ist.
    Wenn es nicht über Endungen funktioniert, wäre eine akzeptable Lösung, eine globale Factory-Methode anzubieten, die das übergebene File einmalig analysiert, daraus den Typ erkennt und eine passende Instanz zurück liefert. Was nicht so schön ist, dass an einer einzigen Stelle bestimmt wird was das für ein Typ ist, und somit die Klasse das nicht selber erledigt, dafür wird die Datei nur einmal geöffnet und gelesen/analysiert.


Log in to reply