Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Вывести список файлов по столбцам


Автор: Nick08 1.11.2012, 19:04
Предложенная программа осуществляет поиск файлов в каталоге.
 Как реализовать (как бы с ключами: /N, /D):

 1)имена файлов(подкаталогов) выводились в крайнем правом столбце (dir /N). Cделал, но коряво, с помощью - cout.width()). Как "нормально" реализовать?

 2)вывод списка в нескольких столбцах с сортировкой по столбцам (dir /D). Тут как сделать???


 
Код

#include <windows.h>
 #include <iostream>
 using namespace std;

 int main()
 {
 WIN32_FIND_DATA fd;

 // находим первый файл
 HANDLE hFindFile = FindFirstFile("C:\\WINDOWS\\*.*", &fd); 
 if (hFindFile == INVALID_HANDLE_VALUE)
 {
 cerr << "Find first file failed." << endl
 << "The last error code: " << GetLastError() << endl;
 cout << "Press any key to finish.";
 }
 else
 {
 // выводим на консоль имя первого файла
 cout.width(70);
 cout << "The first file name: " << fd.cFileName << endl;

 do
 {
 if(fd.cFileName[0] == '.')
 //ПРОПУСКАЕМ СЛУЖЕБНЫЕ ИМЕНА . и ..
 continue;
 else
 // находим следующий файл и выводим на консоль его имя
 cout.width(70);
 cout << fd.cFileName << endl;
 }
 while (FindNextFile(hFindFile, &fd));

 // закрываем дескриптор поиска
 FindClose(hFindFile);
 }
 system("pause");
 return 0;
 }


M
feodorv
Пожалуйста, пользуйтесь кнопкой "Код"

Автор: xvr 3.11.2012, 14:14
Наличие в программе #include <windows.h> и FindFirstFile еще не делают программу системной. Ваша задача не в том, что бы собрать список файлов (это вы сделали), а в том, что бы красиво вывести собранные строки. Это явно задача для другого раздела  smile 

M
xvr
Тему перенес

Автор: Nick08 5.11.2012, 12:05
Понятно...ну а как хотя бы дату и время создания файлов преобразовать к нормальному виду??? Выводится везде 1.1.1601 0:0

#include <windows.h>
 #include <iostream>
 using namespace std;

 int main()
 {
     
 WIN32_FIND_DATA fd;
FILETIME creationTime;
SYSTEMTIME sysTime;
 // находим первый файл
 HANDLE hFindFile = FindFirstFile("C:\\matlab\\*.*", &fd); 
 if (hFindFile == INVALID_HANDLE_VALUE)
 {
 cerr << "Find first file failed." << endl
 << "The last error code: " << GetLastError() << endl;
 cout << "Press any key to finish.";
 }
 else
 {
 // выводим на консоль имя первого файла
 cout.width(60);
 cout << "The first file name: " << fd.cFileName << endl;

 do
 {
 if(fd.cFileName[0] == '.')
 //ПРОПУСКАЕМ СЛУЖЕБНЫЕ ИМЕНА . и ..
 continue;
 else
 // находим следующий файл и выводим на консоль его имя


GetFileTime(hFindFile, &creationTime, 0, 0);
    FileTimeToSystemTime(&creationTime, &sysTime);

 cout.width(60);
 cout << fd.cFileName <<" "<<sysTime.wDay<<"."<<sysTime.wMonth<<"."<<sysTime.wYear<< " "<<sysTime.wHour<<":"<<sysTime.wHour<< endl;
 }
 while (FindNextFile(hFindFile, &fd));

 // закрываем дескриптор поиска
 FindClose(hFindFile);
 }
 system("pause");
 return 0;
 }

Автор: feodorv 5.11.2012, 13:48
Цитата(Nick08 @  5.11.2012,  13:05 Найти цитируемый пост)
 Выводится везде 1.1.1601 0:0

Смотрите. Отсчёт времени в виндах сделан своеобразно - как раз от 1.1.1601 0:0
Цитата

The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). 

И если Вы получаете такое время, то понятно, что в функцию FileTimeToSystemTime Вы отправляете ноль - ноль 100-наносекунд, прошедших с 1 января 1601 года. 

Откуда же взялся 0 в creationTime? А вот откуда:
Цитата(Nick08 @  5.11.2012,  13:05 Найти цитируемый пост)
GetFileTime(hFindFile, &creationTime, 0, 0);

hFindFile - это не хендлер открытого файла, это особый хендлер открытой директории. GetFileTime с ним не справляется и возвращает 0.

Откуда же брать времена интересующего файла? Есть же структура WIN32_FIND_DATA, относящаяся как раз к текущему файлу. А там:
Цитата

typedef struct _WIN32_FIND_DATA {
  DWORD    dwFileAttributes; 
  FILETIME ftCreationTime;                     <<---- 
  FILETIME ftLastAccessTime;                  <<---- 
  FILETIME ftLastWriteTime;                    <<----
  DWORD    nFileSizeHigh; 
  DWORD    nFileSizeLow; 
  DWORD    dwReserved0; 
  DWORD    dwReserved1; 
  TCHAR    cFileName[ MAX_PATH ]; 
  TCHAR    cAlternateFileName[ 14 ]; 
} WIN32_FIND_DATA, *PWIN32_FIND_DATA; 

Автор: Nick08 5.11.2012, 14:04
И как в итоге будет выглядеть код?

Автор: feodorv 5.11.2012, 16:15
Цитата(Nick08 @  5.11.2012,  15:04 Найти цитируемый пост)
И как в итоге будет выглядеть код? 

Гм. Задумался о ключах от квартиры... smile 

Вместо
Цитата(Nick08 @  5.11.2012,  13:05 Найти цитируемый пост)
GetFileTime(hFindFile, &creationTime, 0, 0);
    FileTimeToSystemTime(&creationTime, &sysTime);

нужно сделать:
Код

   FileTimeToSystemTime( &fd.ftCreationTime, &sysTime);

Автор: Nick08 5.11.2012, 17:32
Сделал "проверку" функцией dir с ключом N. Время создания каждого файла отличается на несколько часов (где-то на несколько минут) от результата работы этой проги. В чём причина? (попробуйте проверить сами)

Автор: Nick08 5.11.2012, 18:16
Немного подправил
 #include <windows.h>
 #include <iostream>
 using namespace std;

 int main()
 {

 WIN32_FIND_DATA fd;
 FILETIME creationTime;
 SYSTEMTIME stUTC,stLocal;
 // находим первый файл
 HANDLE hFindFile = FindFirstFile("C:\\Dev-Cpp\\*.*", &fd); 
 if (hFindFile == INVALID_HANDLE_VALUE)
 {
 cerr << "Find first file failed." << endl
 << "The last error code: " << GetLastError() << endl;
 cout << "Press any key to finish.";
 }
 else
 {
 // выводим на консоль имя первого файла
 cout.width(60);
 cout << "The first file name: " << fd.cFileName << endl;

 do
 {
 if(fd.cFileName[0] == '.')
 //ПРОПУСКАЕМ СЛУЖЕБНЫЕ ИМЕНА . и ..
 continue;
 else
 // находим следующий файл и выводим на консоль его имя

 FileTimeToSystemTime( &fd.ftCreationTime, &stUTC);
 SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

 cout.width(60);
 cout << fd.cFileName <<" "<<stLocal.wDay<<"."<<stLocal.wMonth<<"."<<stLocal.wYear<< " "<<stLocal.wHour<<":"<<stLocal.wHour<< endl;
 }
 while (FindNextFile(hFindFile, &fd));

 // закрываем дескриптор поиска
 FindClose(hFindFile);
 }
 system("pause");
 return 0;
 }

Автор: feodorv 5.11.2012, 18:54
Цитата(Nick08 @  5.11.2012,  18:32 Найти цитируемый пост)
Время создания каждого файла отличается на несколько часов (где-то на несколько минут) от результата работы этой проги.

Потому что dir показывает не ftCreationTime, а ftLastWriteTime. Более того, нужно учитывать временной пояс, в котором Вы находитесь:
Код

FILETIME locTime;
if( !FileTimeToLocalFileTime( &fd.ftLastWriteTime, &locTime) ) ...;
if( !FileTimeToSystemTime( &locTime, &stUTC) ) ...;


Потом, у Вас вместо минут часы выводятся, странно, что хоть что-то с чем-то совпадает...

Добавлено через 11 минут и 34 секунды
И пользуйтесь кнопкой код, пожалуйста. Ваши посты выглядят очень неряшливо(((

Автор: Nick08 5.11.2012, 19:12
Ошибка была только в том что вместо минут, я написал часы, а временной пояс оказывается не важным...

Добавлено через 8 минут и 4 секунды
Как теперь вывести список файлов в нескольких столбцах с сортировкой по столбцам. По аналогии с функцией dir с ключом /D... Есть идея - нужно записывать имена файлов в массив. А там уже делать вывод по столбцам. Или не так?

Автор: feodorv 5.11.2012, 19:33
Цитата(Nick08 @  5.11.2012,  20:12 Найти цитируемый пост)
Ошибка была только в том что вместо минут, я написал часы

Только ли? А ftLastWriteTime Вы поправили?

Цитата(Nick08 @  5.11.2012,  20:12 Найти цитируемый пост)
с сортировкой по столбцам

Что под этим имеется в виду? Dir может сортировать по имени, расширению, дате и т.д. А что такое сортировка по столбцам????

Цитата(Nick08 @  5.11.2012,  20:12 Найти цитируемый пост)
Есть идея - нужно записывать имена файлов в массив

Скорее всего, так и нужно будет сделать. Только вопрос: короткие имена файлов или длинные имена?


Автор: Nick08 5.11.2012, 19:38
Да, и ftLastWriteTime.
Запустите в командной строке dir с ключом /D.
Нужно доработать программу так, чтобы вывод был такой же.

Автор: feodorv 5.11.2012, 22:01
Цитата(Nick08 @  5.11.2012,  20:38 Найти цитируемый пост)
Запустите в командной строке dir с ключом /D.

У меня ОС не той системы. Что должно получиться (приведите результат)?

Автор: feodorv 6.11.2012, 06:15
Т.е. сортировка по имени файла (кстати, так и не увидел длинное имя файла - что с ним будет) и вывод в несколько столбцов.
Однозначно сохранять имена файлов и файловые атрибуты в отсортированном массиве (дереве etc). То есть сначала чтение директории/папки целиком (не стоит при этом игнорировать .* файлы), потом вывод в несколько столбцов.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)