crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Работа с recursive_directory_iterator
Bordes
  опции профиля:
сообщение 19.12.2011, 22:36
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 19.12.2011
Пользователь №: 3079

Спасибо сказали: 0 раз(а)




Репутация:   0  


Доброе время суток!

Прошу помощи по решению следующей проблемы:
В приложении (под Windows 7) используется recursive_directory_iterator,
и когда он (итератор) доходит до каталога с запрещенным доступом,
его работа прерывается (по exception).

Вопрос в том, как возобновить работу итератора (после exception) и, пропустив проблемный каталог(и), двигаться по каталогам дальше.

Доп. сведения:
Windows 7 RU, VS 2005, C++
boost 1.46.1

Тестовый пример:

Раскрывающийся текст

#include "stdafx.h"

#include "boost\filesystem.hpp"
#include <iostream>

using namespace std;
using namespace boost;
using namespace boost::filesystem3;

int _tmain(int argc, _TCHAR* argv[])
{
wpath p( L"c:\\" );

// Exception случится, например на "c:\\System Volume Information",
// а как пропустить его и продолжить дальше?

try
{
wrecursive_directory_iterator i( p ), end;

for(; i != end; i++)
{
wcout << *i << std::endl;
}
}
catch (const filesystem_error& ex)
{
wcout << ex.what() << '\n';
}

return 0;
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 20.12.2011, 5:59
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


логично предположить, что вот так

    wrecursive_directory_iterator i( p ), end;

    for(; i != end; i++)
    {
        try
        {
            wcout << *i << std::endl;
        }
        catch (const filesystem_error& ex)
        {
            wcout << ex.what() << '\n';
        }
    }


но такой частый вход в try может замедлить работу, поэтому можно исхитриться с возвратом к выполнению цикла

    {
        wrecursive_directory_iterator i( p ), end;

        bool bNeedContinueAfterExcepted=false;
        do
        {
            try
            {
                for(; i != end; i++)
                {
                    if(bNeedContinueAfterExcepted)
                    {
                        bNeedContinueAfterExcepted=false;
                        continue;
                    }

                    wcout << *i << std::endl;
                }

                bNeedContinueAfterExcepted=false;//эта строчка лишняя, но наглядная
            }
            catch (const filesystem_error& ex)
            {
                wcout << ex.what() << '\n';
                bNeedContinueAfterExcepted=true;
            }
        }
        while(bNeedContinueAfterExcepted);
    }
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Bordes
  опции профиля:
сообщение 20.12.2011, 9:04
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 19.12.2011
Пользователь №: 3079

Спасибо сказали: 0 раз(а)




Репутация:   0  


Спасибо за ответ,
но ничего не получилось -
при возврате в цикл итератор все еще указывает на проблемную директорию и при операции инкремента (именно при инкременте) снова выбрасывается исключение - происходит зацикливание, т.к. итератор не может сдвинуться дальше....
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 20.12.2011, 11:57
Сообщение #4


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


а если без доступа к содержимому делать инкремент - тоже выбрасывается или шагает ? (буста нету, проверить не могу)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 20.12.2011, 12:19
Сообщение #5


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


похоже, это бага буста:
https://svn.boost.org/trac/boost/ticket/4494

впрочем, там что-то написано про передачу параметра конструктору итератора, но я не углублялась. не факт, что эта фича есть у старого буста.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Bordes
  опции профиля:
сообщение 20.12.2011, 19:45
Сообщение #6


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 19.12.2011
Пользователь №: 3079

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Алексей1153 @ 20.12.2011, 11:57) *
а если без доступа к содержимому делать инкремент - тоже выбрасывается или шагает ? (буста нету, проверить не могу)

выбрасывается :(

Цитата(Iron Bug @ 20.12.2011, 12:19) *
похоже, это бага буста:
https://svn.boost.org/trac/boost/ticket/4494

впрочем, там что-то написано про передачу параметра конструктору итератора, но я не углублялась. не факт, что эта фича есть у старого буста.


да, похоже, что бага... и что не закрытая :(
причем, вроде как такое исключение выбрасывается даже в no-throw version of recursive_directory_iterator....
(в которой параметр в конструкторе задается)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 20.12.2011, 20:25
Сообщение #7


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


Цитата(Bordes @ 20.12.2011, 22:45) *
причем, вроде как такое исключение выбрасывается даже в no-throw version of recursive_directory_iterator....
(в которой параметр в конструкторе задается)

ну, как вариант - просто поправить сорцы, как тебе надо. я иногда свои патчи к бусту пишу, если что-то очень нужно :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Bordes
  опции профиля:
сообщение 20.12.2011, 23:31
Сообщение #8


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 19.12.2011
Пользователь №: 3079

Спасибо сказали: 0 раз(а)




Репутация:   0  


О!
Кажется рабочий вариант нашелся: надо в обработчике исключения вызвать для итератора no_push(), после чего при инкременте итератор не пытается "погрузиться" в проблемный каталог.
 try
  {
    wrecursive_directory_iterator i( p ), end;
  
    while ( i != end )
    {
      try
      {
        wcout << *i << std::endl;
        i++;
      }
      catch (const filesystem_error& ex)
      {
        wcout << ex.what() << '\n';
        i.no_push();
        i++; // пропускаем проблемную директорию
      }
    }
  }
  catch (const filesystem_error& ex)
  {
    wcout << ex.what() << L" Bad initial directiry\n";
  }


ЗЫ: Чтой-то пока не готов патчить boost. Тут бы по верхам хоть разобраться :rolleyes:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 21.12.2011, 6:28
Сообщение #9


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


исключения - зло :) А они там, в бусте, не отключаются ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 21.12.2011, 8:03
Сообщение #10


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


Цитата(Алексей1153 @ 21.12.2011, 9:28) *
исключения - зло А они там, в бусте, не отключаются ?

отчего же - зло? при грамотном использовании вполне нормальное решение. когда у тебя куча вложенностей - проще всего кидать исключение и где-то на верхнем уровне, в одном месте, его обрабатывать, чем тащить через все процедуры коды ошибки. особенно если выходов из функции много. а в некоторых случаях (конструкторы) без исключений вообще нельзя сообщить об ошибке.

в бусте исключения не отключаются. они отключаются опцией компилятора (GCC -fno-exceptions, MSVC - по-моему, просто нужно не указывать EH-опции). но не факт, что в таком варианте буст вообще будет как-либо работать. либо можно покопаться в стандартных библиотеках, если перехватить точку входа в обработчик и заменить на свою. но в разных компиляторах они разные. по стандарту в ABI они обзываются Personality Routine. для GCC определение выглядит так:
#define PERSONALITY_FUNCTION __gxx_personality_v0
причём в GCC есть"быстрая" обработка исключений Drarf-2, а есть SJLJ(set jump-long jump), которая в сто раз более тормозная и нужна только для совместимости с системными библиотеками под вендой. а в MSVC SJLJ, без вариантов. но один хрен там компилятор не пересобрать :)

Сообщение отредактировал Iron Bug - 21.12.2011, 8:05
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 16:27