Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с чтением директорий, _finddata_t, _findfirst(), _findnext() 
V
    Опции темы
Acer
Дата 23.8.2008, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: нет
Всего: 8



Доброго времени суток.
OS: Windows XP
Compiler: gcc

Проблема вот в чем:
при чтении подряд двух директорий с путями типа [D:\dir1\subdir1] [D:\dir2\subdir2] все работает нормально.
а вот когда путь типа D:\dir\subdir1 D:\dir\subdir2, то мой метод не работает. То есть на некоторое время зависает программа и потом завершает работу.
вот мой код чтения директорий:
Код

void RFS::readDir(const char *dn, std::vector <_finddata_t>&ddata){
    std::string path( dn );
    struct _finddata_t dd;
    long handle;
    /*проверяем, является ли дерикторией.*/
    if ( !isDir( dn ) ){
        return;
    }
    /*прибавляем к пути '*' */
    if ( path.at( path.size() - 1 ) == '\\' ){
        path.operator +=( '*' );
    } else if ( path.at( path.size() - 1 ) == '/' ){
        path.operator +=( '*' );
    } else {
        path.operator +=( "\\*" );
    }

    if ( ( handle = _findfirst( path.c_str(), &dd ) ) != -1L ){
                /* изменение размера вектора. DIR_SIZE - константа */
        ddata.resize( DIR_SIZE );
        int i = 0;
        while ( !_findnext( handle, &dd ) ){
            if ( RUtil::compareStr( dd.name, ".." ) ) continue;
            ddata[i] = dd;
           /*это для того, чтобы в поле name было не просто имя файла/директории,
            * а полный путь к файлу/директории
            */
            for ( int j = 0; j < FILENAME_MAX; j++ ){
                ddata[i].name[j] = path.substr( 0, path.size() - 1 ).operator +=( dd.name ).c_str()[j];
            }
            i++;
        }
      /* изменение размера вектора. i - количество файлов/директорий в читаемой директории */
        ddata.resize( i );
    }
    _findclose( handle );
}

В метод передается путь к директории ( dn ) и ссылка на std::vector,
в который записываются данные о том, что находится в директории( dn )
PM MAIL   Вверх
andrew_121
Дата 24.8.2008, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



Acer, Что-то ты намудрил тут.
Папример:
Код

path.operator +=( '*' );

А почему не:
Код

path += '*';

И еще:
Код

ddata.resize( DIR_SIZE );

Для чего? Контейнер сам выделяем память.
А это:
Код

           /*это для того, чтобы в поле name было не просто имя файла/директории,
            * а полный путь к файлу/директории
            */
            for ( int j = 0; j < FILENAME_MAX; j++ ){
                ddata[i].name[j] = path.substr( 0, path.size() - 1 ).operator +=( dd.name ).c_str()[j];
            }


Для этого существует рекурсия.
Вот: 

Присоединённый файл ( Кол-во скачиваний: 15 )
Присоединённый файл  scandir.gz 1,36 Kb


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Acer
Дата 25.8.2008, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: нет
Всего: 8



Если можно, ответьте на мой вопрос.
PM MAIL   Вверх
bsa
Дата 25.8.2008, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Acer @ 25.8.2008,  21:20)
Если можно, ответьте на мой вопрос.

А ты задавал вопросы?  smile 

Код
void RFS::readDir(std::string path, std::vector<_finddata_t> &ddata){
    struct _finddata_t dd;
    long handle;
    /*проверяем, является ли дерикторией и допустимый ли путь.*/
    if ( path.empty() || (!isDir( path.c_str() ) ) )
        return;
    /*прибавляем к пути '*' */
    switch(path[path.size() - 1] ) {
       case '\\':
       case '/':
           path += '*';
           break;
       default:
           path += "\\*";
           break;
    }

    if ( ( handle = _findfirst( path.c_str(), &dd ) ) != -1L ){
        while ( !_findnext( handle, &dd ) ){
            if ( (strcmp(dd.name, ".") == 0) || (strcmp( dd.name, ".." ) == 0) )
                continue;
            ddata.push_back(dd); /* добавляем в конец найденный дескриптор */
            _finddata_t &t = ddata.back();
           /*это для того, чтобы в поле name было не просто имя файла/директории,
            * а полный путь к файлу/директории
            * вообще-то это не верно. Так как длина пути может быть N * FILENAME_MAX + 3, где N - количество каталогов, а 3 - "D:\\"
            */
            strncpy(t.name, (path.substr(0, path.size()-1) + dd.name).c_str(), FILENAME_MAX);
            t.name[FILENAME_MAX] = '\0';
        }
    }
    _findclose( handle );
}
Если не заработает, пройдись отладчиком.
И вообще, какие значения параметров ты передаешь на вход?

Это сообщение отредактировал(а) bsa - 25.8.2008, 22:24
PM   Вверх
andrew_121
Дата 25.8.2008, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



Acer, А это не ответ?


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Acer
Дата 25.8.2008, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: нет
Всего: 8



Цитата(bsa @ 25.8.2008,  22:23)
И вообще, какие значения параметров ты передаешь на вход?

указатель на чар - путь к директории.
ссылку на вектор. с нулевым количеством элементов

Это сообщение отредактировал(а) Acer - 25.8.2008, 23:15
PM MAIL   Вверх
bsa
Дата 25.8.2008, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Acer @ 25.8.2008,  23:14)
Цитата(bsa @ 25.8.2008,  22:23)
И вообще, какие значения параметров ты передаешь на вход?

указатель на чар - путь к директории.
ссылку на вектор. с нулевым количеством элементов

просто ты привел пример в начала, что передав одни значения все работает, а с другими нет. Просто то, что ты показал, пары директорий.
PM   Вверх
andrew_121
Дата 26.8.2008, 01:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



bsa, Я ваще не въезжаю...чё ему нужно smile 


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Acer
Дата 26.8.2008, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: нет
Всего: 8



Цитата(andrew_121 @ 26.8.2008,  01:04)
bsa, Я ваще не въезжаю...чё ему нужно smile

Зачем писать, если ты не понимаешь о чем речь?

Добавлено @ 19:18
Цитата(bsa @ 25.8.2008,  23:19)
Цитата(Acer @ 25.8.2008,  23:14)
Цитата(bsa @ 25.8.2008,  22:23)
И вообще, какие значения параметров ты передаешь на вход?

указатель на чар - путь к директории.
ссылку на вектор. с нулевым количеством элементов

просто ты привел пример в начала, что передав одни значения все работает, а с другими нет. Просто то, что ты показал, пары директорий.

Ну так и есть. Пары директорий. Смотри:
программа должна прочитать 2 директории. Всего 2.
Будем читать их двумя способами.
1-й способ:
Читаем директории вот эти:
Код

D:\first_dir
D:\second_dir

Программа читает содержимое директорий тем кодом, который я написал в первом посте.
Вот так идет вызов метода, читающего диретории:
Код

std::vector <_finddata_t>list1;
std::vector <_finddata_t>list2;
RFS::readDir( "D:\\first_dir", list1 );
RFS::readDir( "D:\\second_dir", list2 );

потом делаем вывод списка в консоль.
Вот, что мы увидели после окончания работы программы.
Код

D:\first_dir\sub1
D:\first_dir\sub2
D:\first_dir\file1.cxx
D:\first_dir\file2.cxx
D:\second_dir\sub1
D:\second_dir\sub2
D:\second_dir\file1.cxx
D:\second_dir\file2.cxx

2-й способ. Читаем вот эти директории
Код

D:\Temp\first_dir
D:\Temp\second_dir

(различие в путях видно видно?)
Не важно, что там Temp. Важно то, что first_dir и second_dir - находятся в одной директории.
Вызываем метод чтения так же. Одна, потом вторая.
Так вот во втором случае, код читает только D:\Temp\first_dir. Потом просто зависает. То же самое случается, если читать директории типа:
Код

D:\Temp\first_dir\second_dir\third_dir


Это сообщение отредактировал(а) Acer - 26.8.2008, 19:23
PM MAIL   Вверх
bsa
Дата 27.8.2008, 10:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Дебагер в каком месте показывает зависание?
PM   Вверх
Acer
Дата 27.8.2008, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: нет
Всего: 8



2 bsa
Вобщем, сначала сделал как ты писал. Твой код вообще не работает...
Изначально зависание было на выходе из метода...
Потом в свой код запихнул просто
Код

printf( "" );

вроде бы перестало зависать. То есть проблема была с буфером вывода... где-то что-то оставалось там лишнее. Хотя все указатели удалял... хз. После добавление "пустого" printf появилось зависание в другом месте:
после чтения директорий, при выводе данных в консоль. Я выводил циклом.
Код

std::vector <_finddata_t>list1;
std::vector <_finddata_t>list2;
RFS::readDir( "D:\\first_dir", list1 );
RFS::readDir( "D:\\second_dir", list2 );
for ( int i = 0; i < ( int )list1.size(); i++ ){
    printf( "%s\n", list1[i].name );
}
for ( int i = 0; i < ( int )list2.size(); i++ ){
    printf( "%s\n", list2[i].name );
}

так вот первый цикл проходил нормально, а в конце второго зависало все.
к примеру, во втором 10 элементов. после вывода 10-го элемента прога висла. smile
В данный момент переписал код вот так:
Код

bool RFS::readDir(std::string dn, std::vector <_finddata_t>&ddata){
    if ( !isDir( dn ) ){
        dn.clear();
        return false;
    }
    long handle = 0;
    struct _finddata_t dd;
    bool r = false;

    switch( dn.at( dn.size() - 1 ) ){
        case '\\':
        case '/': dn += '*';
            break;
        case '*': break;
        default: dn += "\\*";
            break;
    }
    if ( ( handle = _findfirst( dn.c_str(), &dd ) ) != -1L ){
        r = true;
        ddata.resize( DIR_SIZE );
        int n = 0;
        while ( !_findnext( handle, &dd ) ){
            if ( ( strcmp( dd.name, "." ) == 0 ) ||
                    ( strcmp( dd.name, ".." ) == 0 ) ){
                continue;
            }
            ddata[n] = dd;
            std::string fl( dn.substr( 0, dn.size() - 1 ) );
            fl += dd.name;
            for ( int i = 0; i < FILENAME_MAX; i++ ){
                ddata[n].name[i] = fl.c_str()[i];
            }
            fl.clear();
            n++;
        }
        ddata.resize( n );
    } else {
        r = false;
    }
    _findclose( handle ) == 0 ? r = true : r = false;
    handle = 0;
    dn.clear();
    return r;
}

без std::vector::resize( size_type ) не работало... Может не грамотно, но работает.
PM MAIL   Вверх
andrew_121
Дата 27.8.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



Цитата(Acer @  26.8.2008,  19:05 Найти цитируемый пост)
Зачем писать, если ты не понимаешь о чем речь?

И не буду! Не мне помощь нужна smile 


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
bsa
Дата 27.8.2008, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Acer, я не утверждал, что мой код работает. Так как я его не проверял. Я просто показал, как примерно это должно выглядеть.
я бы написал через push_back вместо resize...
strncpy не работает?
Код
    if ( !isDir( dn ) ){
        dn.clear();
        return false;
    }
Совершенно бесполезное действие - dn видна только внутри функции.
PM   Вверх
Acer
Дата 27.8.2008, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: нет
Всего: 8



Цитата(bsa @ 27.8.2008,  13:42)
Acer, я не утверждал, что мой код работает. Так как я его не проверял. Я просто показал, как примерно это должно выглядеть.
я бы написал через push_back вместо resize...
strncpy не работает?
Код
    if ( !isDir( dn ) ){
        dn.clear();
        return false;
    }
Совершенно бесполезное действие - dn видна только внутри функции.

strncpy не работает... по поводу string понял.


Вопрос решен.

Это сообщение отредактировал(а) Acer - 27.8.2008, 14:30
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0606 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.