std::filesystem::remove(path, &std::error_code) ???



  • N' Abend,

    ich schlage mich gerade mit der remove-Funktion der STL rum, folgende Methode habe ich:

    void File::deleteFile(const bool ifExists) const
    {
    	if (std::filesystem::is_directory(path))
    	{
    		throw Exception::Exception((std::string)String(PathIsNotAFile, Placeholders::Filename, path.string()), Kernel_StackTraceEntry);
    	}
    	else
    	{
    		std::error_code errorCode;
    
    		if (!std::filesystem::remove(path, errorCode))
    		{
    			if (!ifExists)
    			{
    				throw Exception::System((std::string)String(FileCouldNotBeDeleted, Placeholders::Filename, path.string()), errorCode, Kernel_StackTraceEntry);
    			}
    		}
    	}
    }
    

    Rufe ich die Method auf mit einem Dateinamen, der nicht existiert bekomme ich weder einen Fehlercode noch eine Fehlermessage in der Variablen errorCode. Kann mir einer sagen, was ich falsch mache bzw. wie das funktioniert? Die Beschreibung in der STL online sagt darüber irgendwie nichts genaues aus.

    Vielen Dank im Voraus

    VG Torsten



  • Zu mindestens unter linux mit gcc-10.3.0 liefert std::filesystem::remove(path, errorCode) true zurück wenn die Datei existiert ansonsten false.
    Aber es wird kein error code gesetzt, wenn die Datei nicht existiert.

    Ein ein error code wird gesetzt, wenn z.b. der Prozess nicht die rechte hat die Datei zu löschen.

    Getestet mit folgenden code:

    #include <iostream>
    #include <filesystem>
    namespace fs = std::filesystem;
    int main()
    {
        fs::path tmp = fs::temp_directory_path();
        fs::path filePath = tmp / "test.txt";
        std::error_code errorcode;
        bool result = fs::remove(filePath, errorcode);
        std::cout << "Try deleting " << filePath<< " result: "<<result<<" errorcode:"<<errorcode<<"\n";
    }
    

    Ausgabe wenn die Datei "/tmp/test.txt" nicht existiert:

    Try deleting /tmp/test.txt result: 0 errorcode:system:0
    

    Und hier die Ausgabe wenn die Datei existiert (vorher mit "touch /tmp/test.txt" die Datei angelegt):

    Try deleting /tmp/test.txt result: 1 errorcode:system:0
    

    Und hier die Ausgabe, wenn die Datei existiert aber nicht gelöscht werden kann (z.b. der Prozess hat nicht die Rechte dazu):

    Try deleting "/tmp/test.txt" result: 0 errorcode:generic:1
    

    Der Errorcode 1 ist hier EPERM "Operation not permitted"

    Da unter linux laut der Doku intern unlink genutzt wird bekommt man an den eigentlichen error code via der errno globalen variable.

    Wenn die Datei nicht existiert wird errno auf den wert 2 (ENOENT) gesetzt was "No such file or directory" bedeutet.

    Gut möglich das hier ein Bug in der std::filesystem implementierung in gcc 10.3 existiert der diesen Fehler nicht sauber in einen std::errorcode übertragen wird.



  • G' Morgen,

    danke für die Hilfe. Ich habe bisher nur versucht eine Datei zu löschen, und da kommt eben auch '0' zurück (bei C++20 auf Windows 10), wenn die Datei nicht existiert. Schade eigentlich, da es bedeutet, für diesen Fall die Fehlerbehandlung selbst zu machen.

    Danke nochmal 🙂

    VG Torsten



  • Es kommt auf die Anwendung an, was sie macht und was dargestellt wird, aber eine Datei, die nicht existiert, kann nicht gelöscht werden. Im Grunde kann mit diesem File-Objekt nichts gemacht werden, das zugrunde liegende Element kann auch nicht geöffnet, verschoben oder umbenannt werden.
    Jetzt stellt sich die Frage, warum das versucht wird?

    Filesystem mag für einige Fälle ausreichend sein, unter Windows würde ich für Dateioperationen allerdings die Shell verwenden, da man so auch alles löschen (bzw. in den Papierkorb verschieben) kann. Bei fehlenden Rechten kommt automatisch der UAC prompt.
    Gerade, wenn man diese Informationen auch irgendwie darstellen möchte, gibt es weitere Dinge wie delete on paste, die eine Unterscheidung notwendig machen.

    Ein File-Objekt, das auf kein gültiges Element verweist, würde ich allerdings in jedem Fall direkt als invalid markieren.
    Aber wie geschrieben, es kommt auf den konkreten Anwendungsfall an.


Anmelden zum Antworten