Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   WinApi||посчитать сколько файлов и папок на диске (http://forum.oszone.net/showthread.php?t=76383)

bezumes 18-12-2006 19:53 526298

WinApi||посчитать сколько файлов и папок на диске
 
Здравствуйте. Подскажите пожалуйста, почему у меня при подсчете кол-ва файлов и папок на диске это количество не соответствует действительности.
Код:

for( int i = 0; i < 26; i++ )
{//запускаем цикл с целью опросить все устройства
        if(i==0)
        {
                hFirstFile = FindFirstFile(_T("a:\*.?*"), &wfd);
                hFirstFile1 = FindFirstFile(_T("a:\*."), &wfd);
        }
        else
        if(i==2)
        {                                       
                hFirstFile = FindFirstFile(_T("C:\*.?*"), &wfd);
                hFirstFile1 = FindFirstFile(_T("C:\*"), &wfd);
        }
        else
        if(i==3)
                {
                        hFirstFile = FindFirstFile(_T("d:\*.?*"), &wfd);
                        hFirstFile1 = FindFirstFile(_T("d:\*"), &wfd);
                }
        else
                {
                        hFirstFile = FindFirstFile(_T("bb:\*.?*"), &wfd);
                        hFirstFile1 = FindFirstFile(_T("bb:\*."), &wfd);
                }


    if (hFirstFile != INVALID_HANDLE_VALUE)
        {
                do
                {                                                       
                        nFilesCount =1+nFilesCount;
                }
                  while (FindNextFile(hFirstFile, &wfd));
        }
    if (hFirstFile1 != INVALID_HANDLE_VALUE)
        {
                do
                        {                                                               
                                nFilesCount1 =1+nFilesCount1;                                               
                        }
                while (FindNextFile(hFirstFile1, &wfd));
        }       
    nFilesCount=0;nFilesCount1=0;       
}


Diseased Head 18-12-2006 22:50 526364

Погоди-ка, чёт не понял:

hFirstFile = FindFirstFile(_T("a:\*.?*"), &wfd); // Попытка создать указатель на файлы?

hFirstFile1 = FindFirstFile(_T("a:\*."), &wfd); // Попытка создать указатель на папки?

Так что-ли? А если файл без расшерения? Тогда он будет видится как папка. И почему ты тогда не поставил точки, в следующей части, своего, кода:
Код:

if(i==2)
        {                                       
                hFirstFile = FindFirstFile(_T("C:\*.?*"), &wfd);
                hFirstFile1 = FindFirstFile(_T("C:\*."), &wfd);
        }
        else
        if(i==3)
                {
                        hFirstFile = FindFirstFile(_T("d:\*.?*"), &wfd);
                        hFirstFile1 = FindFirstFile(_T("d:\*."), &wfd);
                }

Я их поставил красным цветом. Или я чёт не допонял...

Vovchick1 18-12-2006 23:06 526374

bezumes
Сам не пробовал, но судя повсему FindFirstFile - найти первый файл, следовательно следующие файлы в каталоге находятся FindNextFile.

Насколько япомню "?" это 1 любой символ, и чем тогда "*.?*" отличается от "*.*"

Diseased Head
"*" это любая последовательность любых символов, а "*." это значет в конце должна стоять точка наример "ReadMe."

Diseased Head 19-12-2006 00:30 526424

Vovchick1
Цитата:

и чем тогда "*.?*" отличается от "*.*"
Да я в общем-то к этому и клонил...
Цитата:

"*" это любая последовательность любых символов, а "*." это значет в конце должна стоять точка наример "ReadMe."
Мож так: "*" значит все файлы и папки (с расширением и без), а "*." папки без расширения и файлы без расширения. Точнее, в конце должна стоять только точка. А можно и так: "*." - "все символы до точки, включая саму точку".

aESThete 19-12-2006 09:37 526543

bezumes
Обратите внимание на неправильный инкремент (лишний "+"):
Код:

if (hFirstFile != INVALID_HANDLE_VALUE)
  {
    do
      {
        nFilesCount +=1+nFilesCount; // и вообще почему не поставить просто nFilesCount++
      }
    while (FindNextFile(hFirstFile, &wfd));
  }

И по маскам: я так понял, что у вас hFirstFile для файлов, а hFirstFile1 для каталогов. Каталоги(папки) тоже могут иметь расширение, так и файлы могут быть без расширения.
Попробуйте сделать одну маску "*.*" и уже потом по атрибутам разделять каталоги и файлы.
Или задача другая: "подсчитать количество отдельно с расширением и без расширения"?

PS для красоты и уменьшения кода я бы посоветовал букву диска формировать.

PPS Только что обратил внимание: вам нужно подсчитать каталоги и папки только в корне диска?

bezumes 19-12-2006 10:43 526575

Цитата:

и чем тогда "*.?*" отличается от "*.*"
как чем, в первом случае расширение 1 символ а во втором любое количество.
Цитата:

Так что-ли? А если файл без расширения? Тогда он будет видится как папка
А нечего такие файлы на диске держать :)
Цитата:

И почему ты тогда не поставил точки, в следующей части, своего, кода
Там я задумывал что найдутся все папки ,неподумал о том что и папки с расширением могут быть, так что А нечего такие папки на диске держать :)
Цитата:

Сам не пробовал, но судя повсему FindFirstFile - найти первый файл, следовательно следующие файлы в каталоге находятся FindNextFile.
Ну у меня же
Код:


 if (hFirstFile != INVALID_HANDLE_VALUE)
{
do
{
//вот только у меня возникают сомнения в правильности выполнения этого цикла
nFilesCount =1+nFilesCount;
}
                  while (FindNextFile(hFirstFile, &wfd));

делать пока новые файлы/папки находит.
Цитата:

Или задача другая: "подсчитать количество отдельно с расширением и без расширения"?
Не, нужно подсчитать количество файлов и папок каждом устройстве
Цитата:

PPS Только что обратил внимание: вам нужно подсчитать каталоги и папки только в корне диска?
Вообще-то нет, но я еще не придумал как искать еще и во вложеных папках.

aESThete 19-12-2006 17:00 526698

bezumes
К сожалению, под рукой C++ освежить в памяти синтаксис и функции нету, а не программировал на С я давно.
Попробую составить примерный алгоритм на "псевдо-C++" (дикой смеси си и васика).
Код:

функция ПосчитатьВсеДиски()
  {
  for( int i = 0; i < 26; i++ ) //запускаем цикл с целью опросить все устройства
    {   
        Файлов = 0;
        Папок = 0;
        ПосчитатьКаталог(char("a"+i) + ":\", Файлов, Папок); // char("a"+i) для переносимости не совсем правильно, надо бы массив букв дисков
        printf("На диске %c  %d файлов, %d папок.", char("a"+i), Файлов, Папок);
    }
  }

функция ПосчитатьКаталог(sStartPath, int *nFilesCount, int *nDirsCount)
  {
    hFirstFile = FindFirstFile(sStartPath+"*.*", &wfd); // ищем первый
    while (hFirstFile != INVALID_HANDLE_VALUE) // пока "найдено"
        {
          if(hFirstFile.attr&АттрибутКаталога != 0 && hFirstFile.name != "." && hFirstFile.name != "..") // если это каталог и не ссылки на себя и на предка (под DOS'ом эти условия нужны были; кстати, будет ли работать под Win без него?)
              {
                nDirsCount++;
                ПосчитатьКаталог(sStartPath+hFirstFile.name, &nFilesCount, &nDirsCount); // рекурсия для найденного подкаталога
              }
          else
              // если это не каталог, знач файл
              nFilesCount++;
          FindNextFile(hFirstFile, &wfd); // ищем следующий
        };
  };

Уф... Надеюсь основную мысль я выразить смог и перевести в нормальный Си у вас получится.

to All
Ногами не пинать! ;) На си не пишу уже давно... Деградировал до VBA и 1С ;)

Diseased Head 19-12-2006 19:56 526776

bezumes
Цитата:

Цитата:

и чем тогда "*.?*" отличается от "*.*"
как чем, в первом случае расширение 1 символ а во втором любое количество.
Один символ, это когда - "*.?". А маски: "*.*", "*.?*", "*.??*" и т. д. - дают идентичный результат.

aESThete
Цитата:

Попробую составить примерный алгоритм на "псевдо-C++" (дикой смеси си и васика).
Так этож новый язык - СиВасик (Casic или C от Васи). :grin:
Цитата:

На си не пишу уже давно... Деградировал до VBA и 1С
Деградация это плохо... :)
Всё нормально... Без обид aESThete... :joke:

aESThete 20-12-2006 08:19 526944

Diseased Head
Цитата:

"*.*", "*.?*", "*.??*" и т. д. - дают идентичный результат.
Не совсем относится к теме, но позвольте не согласиться:
"*.*" - расширение любое (может и пустое)
"*.?*" - расширение не пустое (не менее 1 символа)
"*.??*" - соответственно не менее 2 символов

Diseased Head 20-12-2006 17:13 527156

aESThete, в коммандной строке Win XP (да и в DOS'е), получаем:

dir *,*, dir *,?* и dir *,??* - выводятся все файлы и папки (с расширением и без).
dir *.? - выводятся файлы и папки, с расширением в один символ и без расширения (не более одного символа).

Из книжки В. Э. Фигурнов "IBM PC для пользователя": Символ ? обозначает один произвольный символ или отсутствие символа в имени файла или в расширении имени файла.

Так что ты не прав. К сожалению - НЕ МЕНЕЕ нельзя зделать.

bezumes 21-12-2006 12:20 527491

Все-равно, даже когда я поставил *.* чтобы все посчитать, он мне как-то неправильно считает. Например в корне диска d у меня на два
меньше чем он считает, а на с всего шесть, а он считает 18.
Код:

char temp[100];
        for(int i=0;i<26;i++)
        {               
                hFirstFile=0;
                WIN32_FIND_DATA FindFileData;
                HANDLE hf;               
                if(i==2)
                {
                m_info += " В корне диска C ";
                hf=FindFirstFile("c:\\*.*", &FindFileData);
                //hFirstFile++;
                }
                else
                if(i==3)
                {
                        m_info += " В корне диска D ";
                        hf=FindFirstFile("d:\\*.*", &FindFileData);
                        //hFirstFile++;
                }
                else
                {
                        hf=FindFirstFile("e:\\*", &FindFileData);
                }
                        if (hf!=INVALID_HANDLE_VALUE)
                        {
                                do
                                {                                       
                                        hFirstFile++;
                                }
                                while (FindNextFile(hf,&FindFileData)!=0);

                                itoa( (int)hFirstFile, temp, 10 );
                                m_info += (CString)&temp[0]; m_info += " Файлов и папок";m_info += "\r\n";
                                FindClose(hf);
                        }
        }
        UpdateData(false);

Цитата:

aESThete, в коммандной строке Win XP (да и в DOS'е), получаем:
dir *,*, dir *,?* и dir *,??* - выводятся все файлы и папки (с расширением и без).
dir *.? - выводятся файлы и папки, с расширением в один символ и без расширения (не более одного символа).
Из книжки В. Э. Фигурнов "IBM PC для пользователя": Символ ? обозначает один произвольный символ или отсутствие символа в имени файла или в расширении имени файла.
Так что ты не прав. К сожалению - НЕ МЕНЕЕ нельзя зделать.
А почему тогда, например в стандартном xp поиске *.* это все файлы *.?* файлы с расширением более 1 символа

Diseased Head 21-12-2006 19:32 527667

bezumes
Цитата:

А почему тогда, например в стандартном xp поиске *.* это все файлы *.?* файлы с расширением более 1 символа
Проверил - действительно не более одного символа (я поиском редко пользуюсь). А почему это? Да потому что: программеры в Microsoft напортачили с этим поиском (так как DOS раньше был, и коммандная строка, почему-то, иначе работает). Это, думаю, одна из причин глюков... Или это издёвка над пользователями - что-б жизнь малиной не казалась.

Vovchick1 22-12-2006 01:43 527763

Цитата:

Все-равно, даже когда я поставил *.* чтобы все посчитать, он мне как-то неправильно считает. Например в корне диска d у меня на два меньше чем он считает, а на с всего шесть, а он считает 18.
1. Может скрытые или системные не отображаются.
2. Может переменную "счётчика" не обнулил до начала циклов, и вней присутствуют левые данные.
Цитата:

Например в корне диска d у меня на два меньше чем он считает
3. Не вкурсе насчёт этих функций, но когда ищеш файлы по маске (стандартными средствами Pascal или VB) обычно первые два "файла": ".."
И "..." (Или что-то в этом роде, уже непомню).

aESThete 22-12-2006 08:43 527813

Vovchick1
см. мой исходник: (hFirstFile.name != "." && hFirstFile.name != "..")
это ссылки на себя и на предка (но откуда они в корне?!)
прекрасно видно, если смотреть каталог DiskEdit'ом

Diseased Head
Цитата:

программеры в Microsoft напортачили с этим поиском
это точно, с отдельно стоящим(и) "?" глючок-с
для пробы создал
readme.
readme.t
readme.tx
readme.txt
под XP dir *.*, *.?* и т.д. дают одинаковы е результаты
но read?me (файлов не найдено) и read*me (файлы найдены) отрабатывает чётко

Vovchick1 22-12-2006 11:00 527844

aESThete
Цитата:

см. мой исходник: (hFirstFile.name != "." && hFirstFile.name != "..")
Пардон виноват незаметил!!! :)
Цитата:

это ссылки на себя и на предка (но откуда они в корне?!)
Насчёт ".." вкурсе, а что за "." незнал, будем знать!!! :)
Цитата:

прекрасно видно, если смотреть каталог DiskEdit'ом
Это ты про:
Цитата:

Может скрытые или системные не отображаются.
А насчёт:
Цитата:

Может переменную "счётчика" не обнулил до начала циклов, и вней присутствуют левые данные.

bezumes 22-12-2006 14:21 527961

Цитата:

Может переменную "счётчика" не обнулил до начала циклов, и вней присутствуют левые данные.
Сам счетчик в начале цикла for обнуляется. возможно надо HANDLE hf обнулить. Я попробЫвал написать hf=INVALID_HANDLE_VALUE; и у меня вообще отрицательные значения получились. хотя если в конце стоит FindClose(hf); то этого не надо делать
Код:

        CString bukva[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
        char temp[100];       
        for(int i=0;i<26;i++)
        {               
                hFirstFile=0;//обнуляем
                hFirstFile=0;        // и здесь обнуляем
                WIN32_FIND_DATA lpFindFileData ;
                WIN32_FIND_DATA FindFileData;
                HANDLE hf;       
                hf=INVALID_HANDLE_VALUE;
                hf=FindFirstFile(_T(bukva[i]+":\\*.*"), &FindFileData);
                if (hf!=INVALID_HANDLE_VALUE)
                        {
                                do
                                {hFirstFile=0;hFirstFile=0;
                                       
                                       
                                        if ((FindFileData.dwFileAttributes&&FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
                                        {
                                                hFirstFile++;
                                        }
                                        else
                                        {
                                                hFirstFile1++;
                                        }                                       
                                }
                                while (FindNextFile(hf,&FindFileData)!=0);
                                m_info += " В корне диска "+_T(bukva[i]+" ");
                                itoa( (int)hFirstFile, temp, 10 );
                                m_info += (CString)&temp[0]; m_info += "папок";m_info += "\r\n";
                                m_info += " В корне диска "+_T(bukva[i]+" ");
                                itoa( (int)hFirstFile1, temp, 10 );
                                m_info += (CString)&temp[0]; m_info += " файлов";m_info += "\r\n";
                                FindClose(hf);
                        }
        }
        UpdateData(false);


bezumes 24-12-2006 12:08 528507

В итоге получилось вот так:только долговато ищет(у меня 14.19 сек, а что будет на более слабых компах:) ), ну и результаты от стандартного поиска отличаются(но немного)
Код:

Find(CString(bukva[i])+CString(":"));
Код:

void CSysInfoDlg::Find(CString szPath)
{
CFileFind F;
CString S=szPath+"\\*.*";
BOOL bFlag=F.FindFile(S);
while(bFlag)
{
bFlag=F.FindNextFile();
if(F.IsDirectory()==TRUE && F.IsDots()==FALSE)
{
        p++;       
Find(F.GetFilePath());
}
else
{
        f++;
}
}
F.Close();
}



Время: 06:07.

Время: 06:07.
© OSzone.net 2001-