[Назад] [Далее]

4.8.4. Поиск файлов

Найти нужный файл на диске намного сложнее, чем просто открыть его, — для этого требуются две функции при работе с короткими именами (найти первый файл и найти следующий файл) и три — при работе с длинными именами в DOS 7.0 (найти первый файл, найти следующий файл, прекратить поиск).


Функция DOS 4Eh — Найти первый файл

Ввод: АН = 4Eh
AL используется при обращении к функции APPEND
СХ = атрибуты, которые должен иметь файл (биты 0 (только для чтения) и 5 (архивный бит) игнорируются, если бит 3 (метка тома) установлен, все остальные биты игнорируются)
DS:DX = адрес ASCIZ-строки с именем файла, которое может включать путь и маски для поиска (символы * и ?)
Вывод: CF = 0 и область DTA заполняется данными, если файл найден
CF = 1 и АХ = 02h, если файл не найден, 03h — если путь не найден, 12h — если неправильный режим доступа

Вызов этой функции заполняет данными область памяти DTA (область передачи данных), которая начинается по умолчанию со смещения 0080h от начала блока данных PSP (при запуске СОМ- и ЕХЕ-программ сегменты DS и ES содержат сегментный адрес начала PSP), но ее можно переопределить с помощью функции 1Ah.


Функция DOS 1Ah — Установить область DTA

Ввод: АН = 1Ah
DS:DX = адрес начала DTA (128-байтный буфер)

Функции поиска файлов заполняют DTA следующим образом:

После того как DTA заполнена данными, для продолжения поиска следует вызывать функцию 4Fh, пока не будет возвращена ошибка.


Функция DOS 4Fh — Найти следующий файл

Ввод: АН = 4Fh
DTA — содержит данные от предыдущего вызова функции 4Е или 4F
Вывод: CF = 0 и DTA содержит данные о следующем найденном файле, если не произошла ошибка
CF = 1 и АХ = код ошибки, если произошла ошибка

Для случая длинных имен файлов (LFN) употребляется набор из трех подфункций функции DOS 71h, которые можно использовать, только если запущен IFSmgr (всегда запускается при обычной установке Windows 95, но не запускается, например, с загрузочной дискеты MS-DOS 7.0).


Функция LFN 4Eh — Найти первый файл с длинным именем

Ввод: АХ = 714Eh
CL = атрибуты, которые файл может иметь (биты 0 и 5 игнорируются)
СН = атрибуты, которые файл должен иметь
SI = 0: использовать Windows-формат даты/времени
SI = 1: использовать DOS-формат даты/времени
DS:DX = адрес ASCIZ-строки с маской для поиска (может включать * и ?. Для совместимости маска *.* ищет все файлы в каталоге, а не только файлы, содержащие точку в имени)
ES:DI = адрес 318-байтного буфера для информации о файле
Вывод: CF = 0
АХ = поисковый идентификатор
СХ = Unicode-флаг:
    бит 0: длинное имя содержит подчеркивания вместо непреобразуемых Unicode-символов
    бит 1: короткое имя содержит подчеркивания вместо непреобразуемых Unicode-символов
CF = 1, АХ = код ошибки, если произошла ошибка (7100h — функция не поддерживается)

Если файл, подходящий под маску и атрибуты поиска, найден, область данных по адресу ES:DI заполняется следующим образом:

Причем даты создания/доступа/модификации записываются в одном из двух форматов, в соответствии со значением SI при вызове функции. Windows-формат — 64-битное число 100-наносекундных интервалов с 1 января 1601 года, а если используется DOS-формат — в старшее двойное слово записывается DOS-дата, а в младшее — DOS-время.


Функция LFN 4Fh — Найти следующий файл

Ввод: АХ = 714Fh
ВХ = поисковый идентификатор (от функции 4Eh)
SI = формат даты/времени
ES:DI = адрес буфера для информации о файле
Вывод: CF = 0 и СХ = Unicode-флаг, если следующий файл найден
CF = 1, АХ = код ошибки, если произошла ошибка (7100h — функция не поддерживается)

Функция LFN A1h — Закончить поиск файла

Ввод: АХ = 71A1h
ВХ = поисковый идентификатор
Вывод: CF = 0, если операция выполнена
CF = 1 и АХ = код ошибки, если произошла ошибка (7100h — функция не поддерживается)

В качестве примера программы, использующей многие из функций работы с файлами, рассмотрим программу, заменяющую русские буквы «Н» на латинские «Н» во всех файлах с расширением .ТХТ в текущем каталоге (такая замена требуется для всех текстов, которые будут пересылаться через сеть Fidonet, программное обеспечение которой воспринимает русскую букву «Н» как управляющий символ).

; fidoh.asm
; заменяет русские "Н" на латинские "Н" во всех файлах с расширением .ТХТ
; в текущем каталоге
        .model     tiny
        .code
        org        100h                ; СОМ-файл
start:
        mov        ah,4Eh              ; поиск первого файла
        xor        cx,cx               ; не системный, не каталог и т.д.
        mov        dx,offset filespec  ; маска для поиска в DS:DX
file_open:
        int        21h
        jc         no_more_files       ; если CF = 1 - файлы кончились

        mov        ax,3D02h            ; открыть файл для чтения и записи
        mov        dx,80h+1Eh          ; смещение DTA + смещение имени файла
        int        21h                 ; от начала DTA
        jc         find_next           ; если файл не открылся - перейти
                                       ; к следующему
        mov        bx,ax               ; идентификатор файла в ВХ
        mov        cx,1                ; считывать один байт
        mov        dx,offset buffer    ; начало буфера - в DX
read_next:
        mov        ah,3Fh              ; чтение файла
        int        21h
        jc         find_next           ; если ошибка - перейти к следующему
        dec        ах                  ; если АХ = 0 - файл кончился -
        js         find_next           ; перейти к следующему
        cmp        byte ptr buffer,8Dh ; если не считана русская "Н",
        jne        read_next           ; считать следующий байт,
        mov        byte ptr buffer,48h ; иначе - записать в буфер
                                       ; латинскую букву "Н"
        mov        ax,4201h            ; переместить указатель файла от текущей
        dec        cx                  ; позиции назад на 1
        dec        cx                  ; CX = FFFFh
        mov        dx,cx               ; DX = FFFFh
        int        21h
        mov        ah,40h              ; записать в файл
        inc        cx
        inc        cx                  ; один байт (СХ = 1)
        mov        dx,offset buffer    ; из буфера в DS:DX
        int        21h
        jmp        short read_next     ; считать следующий байт

find_next:
        mov        ah,3Eh              ; закрыть предыдущий файл
        int        21h
        mov        ah,4Fh              ; найти следующий файл
        mov        dx,80h              ; смещение DTA от начала PSP
        jmp        short file_open

no_more_files:                         ; если файлы кончились,
        ret                            ; выйти из программы

filespec      db   "*.txt",0           ; маска для поиска
buffer label  byte                     ; буфер для чтения/записи -
        end        start               ; за концом программы

п»ї
"target=_blank><\/a>") //-->