# Hilfe! Boost::filesystem Exception handling!



## stEEdZ (24. Juni 2008)

Hallo,
ich habe mit der Hilfe von Boost-Libraries ein Filesearch - Programm erstellt.
Das ganze soll dann später Plattformunabhängig laufen, deswegen auch kein Winapi.

Funktioniert übrigens auch sehr gut, mit nur einem Problem:
Wenn vom System der Zugriff auf bestimmte Ordner verweigert wird, bekommt man eine Exception reingeballert und das Programm terminiert!

Hier der Code:

```
#include<boost/filesystem/operations.hpp>
#include<iostream>
#include<string>
#include <exception>
namespace bfs=boost::filesystem;

// Search for a file with the name 'filename' starting in directory 'dir_path', 
// copy the path of the file in 'pfound' if found, and return true.
// Else return false.
bool find_file(const bfs::path & dir_path, const std::string & file_name, bfs::path & pfound)
{
	if( !exists(dir_path) || !is_directory(dir_path) )
		return false;
	bfs::directory_iterator iter(dir_path), end_iter;
	for(; iter!= end_iter; ++iter)
	{
		if( bfs::is_directory(*iter) )
		{
			if( find_file(*iter, file_name, pfound) )
				return true;
		}
		else if( iter->leaf() == file_name )
		{
			pfound = *iter;
			std::cout<<pfound<<std::endl;
			return true;
		}
	}
	return false;
}

int main() { 
    bfs::path my_path("c:\\"); 
    bfs::path temp_path(""); 

    try { 
        if (!find_file(my_path,"test.cpp", temp_path)) 
            std::cout << "Konnte nicht gefunden werden!" << std::endl; 
    } 
    catch (std::exception const& e) { 
        std::cout << "EEEEERROR1elf" << std::endl; 
        std::cout << "type: " << typeid(e).name() << std::endl; 
        std::cout << "message: " << e.what() << std::endl; 
    } 
    system("pause"); 
}
```

Hier der Catch:

```
EEEEERROR1elf
type: class boost::filesystem::basic_filesystem_error<class boost::filesystem::b
asic_path<class std::basic_string<char,struct std::char_traits<char>,class std::
allocator<char> >,struct boost::filesystem::path_traits> >
message: boost::filesystem::basic_directory_iterator constructor: Zugriff verwei
gert: "c:\$Recycle.Bin\S-1-5-21-1829455090-3793272444-3375908254-500"
Drücken Sie eine beliebige Taste . . .
```

In einem anderem Forum wurde bei einem ähnlichem Thema dazu geraten, entweder die Exception zu fangen und zu ignorieren oder eine non-throwing Funktion zu verwenden oder eben die find_file Funktion umzubauen.

Ich bin hier leider total mit meinem Latein am Ende und hoffe auf Hilfe! 
Danke im Vorraus
stEEdZ


----------



## FBIagent (25. Juni 2008)

Morgen,

wie dir schon geraten wurde, würde ich die find_file Funktion verändern, dort die Exception
zu catchen und zu irgnorieren. Ungefähr so:

```
for(; iter!= end_iter; ++iter) 
    {
        try {
            if(bfs::is_directory(*iter) ) 
            { 
                if( find_file(*iter, file_name, pfound) ) 
                    return true; 
            }
            else if( iter->leaf() == file_name ) 
            {
               pfound = *iter; 
                std::cout<<pfound<<std::endl; 
                return true; 
            } 
        } catch ( bsf::basic_filesystem_error &bfe ) {
        }
    }
```

So wird die Exception dann ignoriert und du hast mit den "access denied" keine
probleme mehr. Gegebenfalls überprüfen ob ein anderer Fehler als access denied
vorkommt und diesen handeln.

Best wishes
FBIagent


----------



## deepthroat (25. Juni 2008)

Hi.

Du mußt die Rekursion nicht selbst programmieren. Nimm einfach den recursive_directory_iterator.

Bsp:
	
	
	



```
#include <iostream>

#include <cerrno>

#include <boost/filesystem.hpp>

using std::cout;
using std::cerr;
using std::endl;

using namespace boost::filesystem;

int main() {
  recursive_directory_iterator rdi("/etc");

  while (rdi != recursive_directory_iterator()) {
    cout << rdi->path() << endl;

    if (is_symlink(rdi->symlink_status())) {
      rdi.no_push();
    }

    do {
      try {
         ++rdi;
         break;
      } catch (const filesystem_path_error& e) {
         if (e.system_error() == EACCES) {
            cerr << "error: access denied [" << e.path1() << "]" << endl;
            rdi.no_push();
         } else {
            throw;
         }
      }
    } while (rdi != recursive_directory_iterator());
  }
}
```
Gruß


----------



## stEEdZ (25. Juni 2008)

Hi,
vielen Dank für eure Hilfe!

@FBIagent:
Ich bekomme folgende 2 Fehlermeldungen:

```
error C2955: 'boost::filesystem::basic_filesystem_error' : use of class template requires template argument list
see declaration of 'boost::filesystem::basic_filesystem_error'
error C2316: 'boost::filesystem::basic_filesystem_error &' : cannot be caught as the destructor and/or copy constructor are inaccessible
```

Woran liegt das?


@deepthroat:
Wirklich sehr interessant! Danke! 
Worin liegt der Vorteil des recursive_directory_iterator?

mfg
steedz


----------



## deepthroat (25. Juni 2008)

stEEdZ hat gesagt.:


> @deepthroat:
> Wirklich sehr interessant! Danke!
> Worin liegt der Vorteil des recursive_directory_iterator?


... er arbeitet rekursiv ;-]

Gruß


----------



## stEEdZ (27. Juni 2008)

deepthroat hat gesagt.:


> ... er arbeitet rekursiv ;-]
> 
> Gruß



hehe, das dachte ich mir fast! 

Kann mir jemand zu den Fehlermeldungen helfen? Bin bis jetzt leider noch nicht weiter gekommen 

Danke
steedz


----------



## deepthroat (27. Juni 2008)

stEEdZ hat gesagt.:


> hehe, das dachte ich mir fast!
> 
> Kann mir jemand zu den Fehlermeldungen helfen? Bin bis jetzt leider noch nicht weiter gekommen


Probier's doch mal mit dem filesystem_path_error...

Gruß


----------



## stEEdZ (27. Juni 2008)

hab ich schon probiert 

Da bekomm ich folgende Fehler:

```
error C2039: 'filesystem_path_error' : is not a member of 'boost::filesystem'
error C2061: syntax error : identifier 'filesystem_path_error'
error C2310: catch handlers must specify one type
error C2317: 'try' block starting on line '19' has no catch handlers
```


hier der Code

```
try{
			if( bfs::is_directory(*iter) )
			{
				if( find_file(*iter, file_name, pfound) )
					return true;
			}
			else if( iter->leaf() == file_name )
			{
				pfound = *iter;
				std::cout<<pfound<<std::endl;
				return true;
			}
		}
catch( bfs::filesystem_path_error &e  ){
}
```

Danke für die Hilfe
steedz


----------



## deepthroat (27. Juni 2008)

stEEdZ hat gesagt.:


> hab ich schon probiert
> 
> Da bekomm ich folgende Fehler:
> 
> ...


Aha. Welche Boost Version verwendest du denn?

Gruß


----------



## stEEdZ (27. Juni 2008)

deepthroat hat gesagt.:


> Aha. Welche Boost Version verwendest du denn?
> 
> Gruß



boost_1_35_0, müsste die neueste sein oder?
Muss ich vielleicht noch nen extra Header einbinden?

So sehen meine Includes aus:

```
#include<boost/filesystem/operations.hpp>
#include<boost/filesystem.hpp>
#include<boost/utility.hpp>
#include<iostream>
#include<string>
#include <exception>
namespace bfs=boost::filesystem;
```

danke


----------



## deepthroat (27. Juni 2008)

stEEdZ hat gesagt.:


> boost_1_35_0, müsste die neueste sein oder?


Ja. Es scheint da gab es eine Umbenennung (ich hab hier 1.34). Warum schaust du denn aber nicht einfach in den Boost Headern nach?

Probier's mit filesystem_error.

Gruß


----------



## stEEdZ (27. Juni 2008)

deepthroat hat gesagt.:


> Probier's mit filesystem_error.
> 
> Gruß



Es geht! Oh man danke du glaubst gar nicht wie happy ich gerade bin! 

Gibt es mit Boost eigentlich eine equivalente Lösung zu "GetLogicalDriveStrings" und "GetDriveType"?

Danke im Voraus
steedz


----------

