Пятница, 18.07.2025, 20:48 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 5. Управление файлами(2)

II

Поиск файлов. Для поиска файлов в Windows существуют две функции FindFirstFile и FindNextFile, очень похожие на аналогичные функции MS DOS и, как и там, работающие в паре. При успешном поиске первая функция возвращает некое число или идентификатор, который затем используется второй функцией для продолжения поиска.

Первым параметром функции FindFirstFile является указатель на строку для поиска файлов, второй параметр - указатель на структуру, которая получает информацию о найденных файлах. Функция FindNextFile первым своим параметром имеет идентификатор, полученный первой функцией, а вторым параметром - указатель на структуру. Эту структуру можно изучить по программе на Рис. 2.5.1.

Основным отличием этих функций от соответствующих функций MS DOS является то, что поиск ограничивается только маской поиска (*.*, *.ЕХЕ и т.п.). Если файл найден, то тогда по возвращаемой структуре, где содержится вся информация о нем, Вы уже можете решать, подходит файл или нет.

На Рис. 2.5.1 представлена программа, осуществляющая поиск файлов в указанном каталоге. Программа может иметь один или два параметра, или не иметь их вовсе. Если имеются два параметра, то первый параметр трактуется как каталог для поиска, причем программа учитывает, есть ли на конце косая черта или нет (допустимо c:, c:\, c:\windows\, c:\windows\system и т.п.). Второй параметр (в программе он третий, так как первым считается командная строка), если он есть, представляет собой маску поиска. Если его нет, то маска поиска берется в виде "*.*". Наконец, если параметров нет вообще, то поиск осуществляется в текущем каталоге по маске "*.*". Эту программу легко развить и сделать из нее полезную утилиту. Предоставляю это Вам, дорогой читатель. Ниже будет дан комментарий к означенной программе.

; файл FILES.ASM
.386P
; плоская модель
.MODEL FLAT, stdcall
; константы
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
; прототипы внешних процедур
EXTERN wsprintfA:NEAR
EXTERN CharToOemA@8:NEAR
EXTERN GetStdHandle@4:NEAR
EXTERN WriteConsoleA@20:NEAR
EXTERN ReadConsoleA@20:NEAR
EXTERN ExitProcess@4:NEAR
EXTERN GetCommandLineA@0:NEAR
EXTERN lstrcatA@8:NEAR
EXTERN FindFirstFileA@8:NEAR
EXTERN FindNextFileA@8:NEAR
EXTERN FindClose@4:NEAR
;-----------------------------
; структура, используемая для поиска файла
; при помощи функций FindFirstFile и FindNextFile
_FIND STRUC
; атрибут файла
 ATR DWORD ?
; время создания файла
 CRTIME DWORD ?
 DWORD ?
; время доступа к файлу
 ACTIME DWORD ?
 DWORD ?
; время модификации файла
 WRTIME DWORD ?
 DWORD ?
; размер файла
 SIZEH DWORD ?
 SIZEL DWORD ?
; резерв
 DWORD ?
 DWORD ?
; длинное имя файла
 NAM DB 260 DUP (0)
; короткое имя файла
 ANAM DB 14 DUP(0)
_FIND ENDS
;-------------------------------------------------
; директивы компоновщику для подключения библиотек
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
;-------------------------------------------------

; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 BUF DB 0
 DB 100 dup(0)
 LENS DWORD ? ; количество выведенных символов
 HANDL DWORD ?
 HANDL1 DWORD ?
 MASKA DB "*.*",0
 АР DB "\",0
 FIN _FIND <0>
 TEXT DB "Для продолжения нажмите клавишу ENTER",13,10,0
 BUFIN DB 10 DUP(0)
 FINDH DWORD ?
 NUM DB 0
 NUMF DWORD 0 ; счетчик файлов
 NUMD DWORD 0 ; счетчик каталогов
 FORM DB "Число найденных файлов: %lu",0
 FORM1 DB "Число найденных каталогов: %lu",0
 BUFER DB 100 DUP (?)
 DIR DB "<DIR>",0
 PAR DB 0 ; количество параметров
_DATA ENDS


; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:
; получить HANDLE вывода
 PUSH STD_OUTPUT_HANDLE
 CALL GetStdHandle@4
 MOV HANDL,EAX
; получить HANDL1 ввода
 PUSH STD_INPUT_HANDLE
 CALL GetStdHandle@4
 MOV HANDL1,EAX
; преобразовать строки для вывода
 PUSH OFFSET TEXT
 PUSH OFFSET TEXT
 CALL CharToOemA@8
 PUSH OFFSET FORM
 PUSH OFFSET FORM CALL
 CharToOemA@8
 PUSH OFFSET FORM1
 PUSH OFFSET FORM1
 CALL CharToOemA@8
; получить количество параметров
 CALL NUMPAR
 MOV PAR,EAX
; если параметр один, то искать в текущем каталоге
 CMP EAX, 1
 JE NO_PAR
;-------------------------------------------------
; получить параметр номером EDI
 MOV EDI, 2
 LEA EBX,BUF
 CALL GETPAR
 PUSH OFFSET BUF
 CALL LENSTR
; если в конце нет "\" - добавим
 CMP BYTE PTR [BUF+EBX-1],"\"
 JE NO_PAR
 PUSH OFFSET AP
 PUSH OFFSET BUF
 CALL lstrcatA@8
; нет ли еще параметра, где задана маска поиска
 CMP PAR,3
 JB NO_PAR
; получить параметр - маску поиска
 MOV EDI,3
 LEA EBX,MASKA
 CALL GETPAR
NO_PAR:
;-------------------------------------------------
 CALL FIND
; вывести количество файлов
 PUSH NUMF
 PUSH OFFSET FORM
 PUSH OFFSET BUFER
 CALL wsprintfA
 LEA EAX, BUFER
 MOV EDX,1
 CALL WRITE
; вывести количество каталогов
 PUSH NUMD
 PUSH OFFSET FORM1
 PUSH OFFSET BUFER
 CALL wsprintfA
 LEA EAX, BUFER
 MOV EDX, 1
 CALL WRITE
_END:
 PUSH 0
 CALL ExitProcess@4
;************************
; область процедур
;************************
; вывести строку (в конце перевод строки)
; EAX - на начало строки
; EDX - с переводом строки или без
WRITE PROC
; получить длину параметра
 PUSH EAX
 CALL LENSTR
 MOV ESI,EAX
 CMP EDX,1
 JNE NO_ENT
; в конце - перевод строки
 MOV BYTE PTR [EBX+ESI],13
 MOV BYTE PTR [EBX+ESI+1],10
 MOV BYTE PTR [EBX+ESI+2],0
 ADD EBX,2
NO_ENT:
; вывод строки
 PUSH 0
 PUSH OFFSET LENS
 PUSH EBX
 PUSH EAX
 PUSH HANDL
 CALL WriteConsoleA@20
 RET
WRITE ENDP

; процедура определения длины строки
; строка - [EBP+08Н]
; длина в EBX
LENSTR PROC
 PUSH EBP
 MOV EBP,ESP
 PUSH EAX
;----------------------
 CLD
 MOV EDI, DWORD PTR [EBP+08Н]
 MOV EBX, EDI
 MOV ECX,100 ; ограничить длину строки
 XOR AL,AL
 REPNE SCASB ; найти символ 0
 SUB EDI, EBX ;-длина строки, включая 0
 MOV EBX, EDI
 DEC EBX 
;----------------------
 POP EAX
 POP EBP
 RET 4
LENSTR ENDP

; процедура определения количества параметров в строке
; определить количество параметров (->EAX)
NUMPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI],0
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX, 0
 JMP L2
L3:
 OR EDX,1
L2:
 INC ESI 
 JMP L1
L4:
 MOV EAX,ECX
 RET
NUMPAR ENDP

; получить параметр из командной строки
; EBX - указывает на буфер, куда будет помещен параметр
; в буфер помещается строка с нулем на конце
; EDI - номер параметра
GETPAR PROC
 CALL GetCommandLineA@0
 MOV ESI, EAX ; указатель на строку
 XOR ECX, ECX ; счетчик
 MOV EDX, 1 ; признак
L1:
 CMP BYTE PTR [ESI], 0
 JE L4
 CMP BYTE PTR [ESI], 32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 CMP ECX,EDI
 JNE L5
 MOV AL,BYTE PTR [ESI]
 MOV BYTE PTR [EBX],AL
 INC EBX
L5:
 INC ESI
 JMP L1
L4:
 MOV BYTE PTR [EBX], 0
 RET
GETPAR ENDP

; поиск в каталоге файлов и их вывод
; имя каталога в BUF
FIND PROC
; путь с маской
 PUSH OFFSET MASKA
 PUSH OFFSET BUF
 CALL lstrcatA@8
; здесь начало поиска
 PUSH OFFSET FIN
 PUSH OFFSET BUF
 CALL FindFirstFileA@8
 CMP EAX,-1
 JE _ERR
; сохранить дескриптор поиска
 MOV FINDH,EAX
LF:
; исключить "файлы" "." и ".."
 CMP BYTE PTR FIN.NAM,"."
 JE _NO
; не каталог ли?
 TEST BYTE PTR FIN.ATR,10H
 JE NO_DIR
 PUSH OFFSET DIR
 PUSH OFFSET FIN.NAM
 CALL lstrcatA@8
 INC NUMD
 DEC NUMF
NO_DIR:
; преобразовать строку
 PUSH OFFSET FIN.NAM
 PUSH OFFSET FIN.NAM
 CALL CharToOemA@8
; здесь вывод результата
 LEA EAX, FIN.NAM
 MOV EDX,1
 CALL WRITE
; увеличить счетчики
 INC NUMF
 INC NUM
; конец страницы?
 CMP NUM, 22
 JNE _NO
 MOV NUM, 0
; ждать ввод строки
 MOV EDX,0
 LEA EAX, TEXT
 CALL WRITE
 PUSH 0
 PUSH OFFSET LENS
 PUSH 10
 PUSH OFFSET BUFIN
 PUSH HANDL1
 CALL ReadConsoleA@20
_NO:
; продолжение поиска
 PUSH OFFSET FIN
 PUSH FINDH
 CALL FindNextFileA@8
 CMP EAX,0
 JNE LF
; закрыть поиск
 PUSH FINDH
 CALL FindClose@4
_ERR:
 RET
FIND ENDP
_TEXT ENDS
END START

Рис. 2.5.1 Пример простой программы, которая осуществляет поиск файлов и выводит их название на экран.


Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 2
    Гостей: 2
    Пользователей: 0