GetCurrentDir — Функция Delphi

GetCurrentDir — Функция Delphi

Здраствуйте, Уважаемые Мастера.
Подскажите, как определить директорию, из которой было запушенно приложение. При загрузке моя программа считывает из Ini-файла, который лежит там же где и сама программа, конфигурационные параметры, но возникла проблема переноса проги в другую директорию => надо определить, что бы приложение определяло директорию откуда оно запускается
Заранее благодарю за помощь
с уважением.

to GrazyAngel
Огромное спасибо

ExtractFilePath (ParamStr (0))

GetCurrentDir — неверный ответ. Вполне возможна ситуация, когда он укажет на другую папку.
Правильный ответ
>MAxiMum © (28.03.02 17:54)

или можно
ExtractFilePath(Application.Exename)

кстати, GetCurrentDir в общем случае даст не тот эффект.

А когда такое может случиться ? Набудущее .

например, попробуй запустить свою Пуск-выполнить или поместив ярлык на рабочий стол, и запустить оттуда.
Одно лишь точно — GetCurrentDir 100% будет указывать на папку программы только тогда, когда программа запущена двойным кликом по исполняемому файлу, или же набором имени программы в файл-менеджере, находясь при этом в папке программы

а.. ещё забыл, кажется она ещё будет работать как надо, если запустить проект из Дельфи :-)

Сплошь и рядом.
Например при запуске с ярлыка, у которого не прописан рабочий путь.
Или при работе с OpenDialog — он меняет CurrentDir.

>CrazyAngel © (28.03.02 18:03)
Например, когда будет выполнена функция SetCurrentDir.

GetCurrentDir — Функция Delphi

При первом запуске после инсталлятора, моя программа начинает капитально глючить. Выяснил, что проблема с GetCurrentDir. По идее (моей) функция должна возвращать текущий путь к папке из которой, запускается программа, а по факту возвращается путь, не имеющий к программе никакого отношения. После нескольких запусков ситуация нормализуется. При чем эффект наблюдается именно в процессе первых запусков после инсталляции программы InstallShield-ом. Простое копирование побочных эффектов не дает.

Как с этим бороться?

есть апишная функция GetCurrentDirectory
попробуй ею. Только результат будет скорее всего такой же

GetCurrentDir возвращает вообще-то не каталог, в котором запускается программа, а текущий каталог программы. Это не одно и тоже. Например, если ты в процессе работы открываешь какой-то файл, то после этого GetCurrentDir вернет именно этот каталог. Еще вот в Ворде мы сохраняем файл. Автоматом открывается «Мои документы» — это и есть каталог программы, а не тот в котором word.exe находится.

Узнай директорию из которой запускалась прога через:Application->ExeName;

Добавлено в 26.08.04, 13:38 :
Хи-хи.
Одновременно ответили. Бывает же!

Скорей всего она возвращает каталог, из которого ты запускал инсталлятор. Я тоже с этим сталкивался. Поэтому нужно просто ExtractFilePath(Application->ExeName).

Добавлено в 26.08.04, 13:54 :
да, бывает

setcurrentdir

Автор Vladimir Kurov задал вопрос в разделе Другие языки и технологии

delphi — функция setcurrentdir (chDir), не переходит в каталог и получил лучший ответ

Ответ от . . r. u[гуру]
логично предположить, что раз папка сетевая, то может быть ограничен доступ к этой папке.. только не задавайтесь вопросом типа «почему в папку 3 можно, а в папку 2 нет? » ибо права выставляются именно на объекты, путь роли не играет. при создании дочернего объекта, он наследует родительские права, которые впоследствии изменяются индивидуально

Типы, функции и процедуры Delphi для работы с файлами.

Содержание:


Процедуры и функции для работы с файлами.


Тип TSearchRec.


Тип TWin32FindData.


Процедуры и функции для работы с файлами

Ниже приведена таблица, содержащая стандартные процедуры и функции Delphi7 для работы с файлами и их краткое описание. Функции в таблице расположены в алфавитном порядке.

Связывает имя внешнего дискового файла с файловой переменной.

procedure AssignFile(var F; FileName: string);

F — имя файловой переменной
FileName — имя файла

Изменяет текущую директорию.

procedure ChDir(const S: string); overload;
procedure ChDir(P: PChar); overload;

Разрывает связь между файловой переменной и внешним дисковым файлом.

procedure CloseFile(var F);

Создает новую директорию.

function CreateDir(const Dir: string): Boolean;

Удаляет файл с диска.

function DeleteFile(const FileName: string): Boolean;

Определяет существует ли указанная директория.

function DirectoryExists(const Directory: string): Boolean;

Возвращает число свободных байт на указанном диске.

function DiskFree(Drive: Byte): Int64;

Drive — номер диска, где 0 = текущий диск, 1 = A, 2 = B . и т.д.

Возвращает размер указанного диска в байтах.

function DiskSize(Drive: Byte): Int64;

Drive — номер диска, где 0 = текущий диск, 1 = A, 2 = B . и т.д.

Возвращает время последней модификации файла (timestamp) в формате операционной системы. Полученное значение может быть преобразовано в формат TDateTime при помощи функции FileDateToDateTime.

function FileAge(const FileName: string): Integer;

Закрывает указанный файл.

procedure FileClose(Handle: Integer);

Создает новый файл.

function FileCreate(const FileName: string): Integer; overload;
function FileCreate(const FileName: string; Rights: Integer): Integer; overload;

Если возвращаемое значение больше 0 функция выполнена успешно и его значение соответствует handle открытого файла. -1 — произошла ошибка открытия файла.
Параметр Rights используется только для Linux. В Windows он игнорируется.

Преобразует значение времени файла (timestamp) из формата операционной системы в TDateTime.

function FileDateToDateTime(FileDate: Integer): TDateTime;

Проверяет существует ли указанный файл.

function FileExists(const FileName: string): Boolean;

Возвращает файловые аттрибуты заданного файла как строку бит. Возвращаемое значение полностью соответствует полю Attr в TSearchRec..

function FileGetAttr(const FileName: string): Integer;

Возвращает время последней модификации файла (timestamp) в формате операционной системы. Используйте её для файла, заданного его handle.

function FileGetDate(Handle: Integer): Integer;

Возвращает TRUE если файл можно открыть только для чтения.

function FileIsReadOnly(const FileName: string): Boolean;

Открывает указанный файл в режиме, заданном при помощи одной из констант File open mode.

function FileOpen(const FileName: string; Mode: LongWord): Integer;

Если возвращаемое значение больше 0 функция выполнена успешно и его значение соответствует handle открытого файла. -1 — произошла ошибка открытия файла.

Читает указанное число байт из файла в буфер. Перед этим файл должен быть открыт при помощи функции FileOpen или FileCreate.

function FileRead(Handle: Integer; var Buffer; Count: Integer): Integer;

Handle — хендл файла, возвращаемый функциями FileCreate или FileOpen
Buffer — буфер
Count — размер буфера

Возвращаемое значение — действительное количество полученных байт. Оно может быть меньше размера буфера.

Ищет файл в указанных папках.

function FileSearch(const Name, DirList: string): string;

Name — короткое имя файла
DirList — список директорий для поиска. Для Windows директории для поиска в списке отделяются друг от друга точкой с запятой, а в Linux — двоеточием.

Возвращаемое значение — полное имя файла. Если файл не найден — пустая строка.

Перепозиционирует позицию чтения/записи в открытом файле. Перед этим файл должен быть открыт при помощи функции FileOpen или FileCreate.

function FileSeek(Handle, Offset, Origin: Integer): Integer; overload;
function FileSeek(Handle: Integer; const Offset: Int64; Origin: Integer): Int64;overload;

Handle — хендл файла, возвращаемый функциями FileCreate или FileOpen
Offset — указывает число байт смещения от Origin, куда будет перепозизиционирована точка.
Origin — определяет три варианта позиционирования:
0 — смещение задается относительно начала файла;
1 — смещение задается относительно текущей позиции;
2 — смещение задается относительно конца файла.

Если FileSeek выполнена успешно, она возвращает новую позицию точки чтения/записи; иначе она возвращает -1.

Устанавливает файловые аттрибуты заданного файла.

function FileSetAttr(const FileName: string; Attr: Integer): Integer;

Значение Attr формируется комбинацией соответствующих констант файловых аттрибутов как показано ниже:

Возвращаемое значение — 0; иначе — код ошибки.

Примечание: Значения констант файловых аттрибутов приведены в описании TSearchRec.

Примечание: FileSetAttr доступна только для Windows.

Устанавливаетвремя последней модификации файла (timestamp) в формате операционной системы.

Для Windows:
function FileSetDate(Handle: Integer; Age: Integer): Integer; overload;

Cross-platform:
function FileSetDate(const FileName: string; Age: Integer): Integer; overload;

Handle — handle файла для изменения (Этот синтаксис доступен только для Windows.);
FileName — имя файла;
Age — устанавливаемое время модификации в формате операционной системы. Используйте функцию DateTimeToFileDate для перевод времени из формата TDateTime в формат операционной системы.

Возвращаемое значение — 0; иначе — код ошибки.

Разрешает использовать файл только для чтения.

function FileSetReadOnly(const FileName: string; ReadOnly: Boolean): Boolean;

Записывает содержимое буфера в текущую позицию в файле.

function FileWrite(Handle: Integer; const Buffer; Count: Integer): Integer;

Handle — хендл файла, возвращаемый функциями FileCreate или FileOpen
Buffer — буфер
Count — число байт, передаваемых файлу из буфера

Возвращаемое значение — действительное количество записаных байт или -1 в случае ошибки.

Освобождает память, выделенную под функцию FindFirst и прерывает последовательность FindFirst/FindNext.

Ищет первый файл с заданными аттрибутами в указанной папке.

function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer;

Path — имя папки и маска имен файлов для поиска, включая wildcard characters. (Например, ‘.\test\*.*’ задает все файлы в текущей папке.)
Attr — аттрибут, указывающий включать в поиск специальные файлы в дополнение к нормальным. Аттрибуты можно комбинировать, складывая значения. Например, (faReadOnly + faHidden).
F — возвращаемый параметр. Результат работы функции.

Возвращаемое значение — 0, если файл найден; иначе — код ошибки.

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

F — возвращаемый параметр. Результат работы функции.

Возвращаемое значение — 0, если файл найден; иначе — код ошибки.

Создает новую папку, включая родительские папки, если они до этого не существовали, и родительские папки.

function ForceDirectories(Dir: string): Boolean;

Возвращает полное имя рабочей папки.

function GetCurrentDir: string;

Возвращает имя рабочей папки.

procedure GetDir(D: Byte; var S: string);

D — номер диска, где 0 = текущий диск, 1 = A, 2 = B, 3 = C . и т.д.
S — возвращаемый параметр. Результат работы процедуры.

Удаляет существующую пустую папку.

function RemoveDir(const Dir: string): Boolean;

Изменяет имя файла.

function RenameFile(const OldName, NewName: string): Boolean

Назначает рабочую папку.

function SetCurrentDir(const Dir: string): Boolean;

Тип TSearchRec

TSearchRec содержит информацию о файле, найденом при помощи функции FindFirst или FindNext.

Тип TSearchRec определяет информацию о файле, найденую путем вызова функции FindFirst или FindNext. Если файл найлен, поля параметров TSearchRec изменяются в соответствии с найденным файлом.

Attr — представляет файловые аттрибуты файла. Проверяйте параметр Attr на следующие константы аттрибутов или их значения чтобы узнать какие аттрибуты назначены данному файлу.

В Windows константы аттрибутов полностью соответствуют файловым аттрибутам DOS.

Наименование Тип
модуль
Описание
AssignFile процедура
System
ChDir процедура
System
CloseFile процедура
System
CreateDir функция
SysUtils
DeleteFile функция
SysUtils
DirectoryExists функция
SysUtils
DiskFree функция
SysUtils
DiskSize функция
SysUtils
File mode константы
System
Используются для открытия и закрытия дисковых файлов.

const fmClosed = $D7B0; // closed file
const fmInput = $D7B1; // reset file (TTextRec)
const fmOutput = $D7B2; // rewritten file (TTextRec)
const fmInOut = $D7B3; // reset or rewritten file (TFileRec)
const fmCRLF = $8; // DOS-style EoL and EoF markers (TTextRec)
const fmMask = $D7B3; // mask out fmCRLF flag (TTextRec)

Эти константы используются в первую очередь в Delphi коде, где поле Mode в TFileRec и TTextRec содержит одно из этих значений.

File open mode константы
SysUtils
Константы режима открытия файла используются для контроля режима доступа к файлу или потоку.

Для Windows:

Эти константы используются для конроля режима совместного доступа при открытии файла или потока.

TFileStream конструктор имеет параметр Mode в котрый вы можете прописать одну из следующих констант:

Константа Описание
fmCreate Если файл уже существует, то он открывается для записи, иначе создается новый файл. В отличие от других констант, которые декларируются в модуле SysUtil, эта константа декларируется в модуле classes.
fmOpenRead Открываетдоступ только для чтения.
fmOpenWrite Открываетдоступ только для записи.
fmOpenReadWrite Открывает доступ для чтения и записи.
fmShareCompat Compatible with the way FCBs are opened. Не используйте этот режим в кросс-платформенных приложениях.
fmShareExclusive Доступ к чтению и записи запрещен.
fmShareDenyWrite Доступ для записи запрещен.
fmShareDenyRead Доступ для чтения запрещен. Не используйте этот режим в кросс-платформенных приложениях.
fmShareDenyNone Открывает полный доступ для других.
FileAccessRights пременная Points to the command-line arguments specified when the application is invoked. Только для Linux. В Windows эта переменная игнорируется.
FileAge функция
SysUtils
FileClose процедура
SysUtils
FileCreate функция
SysUtils
FileDateToDateTime функция
SysUtils
FileExists функция
SysUtils
FileGetAttr функция
SysUtils
FileGetDate функция
SysUtils
FileIsReadOnly функция
SysUtils
FileOpen функция
SysUtils
FileRead функция
SysUtils
FileSearch функция
SysUtils
FileSeek функция
SysUtils
FileSetAttr функция
SysUtils
FileSetDate функция
SysUtils
FileSetReadOnly функция
SysUtils
FileWrite функция
SysUtils
FindClose процедура
SysUtils
FindFirst функция
SysUtils
FindNext функция
SysUtils
ForceDirectories функция
SysUtils
GetCurrentDir функция
SysUtils
GetDir процедура
System
RemoveDir функция
SysUtils
RenameFile функция
SysUtils
SetCurrentDir функция
SysUtils
Константа Значение Описание
faReadOnly 1 Файлы Только для чтения
faHidden 2 Скрытые файлы
faSysFile 4 Системные файлы
faVolumeID 8 Файлы идентификации тома
faDirectory 16 Файлы папок
aArchive 32 Архивные файлы
faSymLink 64 Символьная ссылка
faAnyFile 71 Любые файлы

Примечание:
Константа faReadOnly из модуля SysUtils имеет то же самое имя, что и константа из модуля Db, определенная в типе TFieldAttribute. Если в своих исходниках вы одновременно используете модули SysUtils и Db, то, чтобы исключить неопределенность, необходимо конкретно указывать из какого модуля вы используете значение константы faReadOnly. В Delphi это записывается так: SysUtils.faReadOnly.

Чтобы проверить файл на определенный аттрибут, комбинируйте значение поля Attr с соотвтствующей константой при помощи оператора AND. Если файл имеет этот аттрибут, результат будет больше 0. Например, если найденый файл является скрытым, то следующие выражения дадут значение TRUE:

Time содержит время последнего изменения файла. Оно может быть преобразовано в формат TDateTime при помощи функции FileDateToDateTime.

Size содержит размер файла в байтах.

Name содержит короткое имя файла с расширением.

FindHandle is an internal handle used to track find state.

FindData (только для Windows) содержит дополнительную информацию, такую как время создания файла, время последнего доступа, а так же длинное и короткое имя файла. См. тип TWin32FindData.

GetCurrentDir — Функция Delphi

Во время работы каждого приложения для него запоминается папка, которая считается текущей (для этого приложения). При грамотном управлении текущей папкой удобно использовать рассмотренные далее относительные пути.

Для определения текущей папки приложения можно воспользоваться функцией GetCurrentDir, приведенной в листинге 4.16.

function GetCurrentDir(): String;

SetLength(buffer, MAX_PATH + 1);

len := GetCurrentDirectory(MAX_PATH, PAnsiChar(buffer));

GetCurrentDir := Copy(buffer, 1, len);

Функция определения пути текущей папки основана на применении соответствующей API-функции GetCurrentDirectory. Вполне естественно, что она имеет пару – функцию для задания текущего каталога SetCurrentDirectory. Объявление этой функции:

function SetCurrentDirectory(lpPathName: PChar): BOOL; stdcall;

Функция принимает путь папки и возвращает ненулевое значение в случае успешного выполнения.

GetCurrentDirectory function

Retrieves the current directory for the current process.

Syntax

Parameters

The length of the buffer for the current directory string, in TCHARs. The buffer length must include room for a terminating null character.

A pointer to the buffer that receives the current directory string. This null-terminated string specifies the absolute path to the current directory.

To determine the required buffer size, set this parameter to NULL and the nBufferLength parameter to 0.

Return Value

If the function succeeds, the return value specifies the number of characters that are written to the buffer, not including the terminating null character.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

If the buffer that is pointed to by lpBuffer is not large enough, the return value specifies the required size of the buffer, in characters, including the null-terminating character.

Remarks

Each process has a single current directory that consists of two parts:

  • A disk designator that is either a drive letter followed by a colon, or a server name followed by a share name (\\servername\sharename)
  • A directory on the disk designator

To set the current directory, use the SetCurrentDirectory function.

Multithreaded applications and shared library code should not use the
GetCurrentDirectory function and should avoid using relative path names. The current directory state written by the SetCurrentDirectory function is stored as a global variable in each process, therefore multithreaded applications cannot reliably use this value without possible data corruption from other threads that may also be reading or setting this value. This limitation also applies to the SetCurrentDirectory and GetFullPathName functions. The exception being when the application is guaranteed to be running in a single thread, for example parsing file names from the command line argument string in the main thread prior to creating any additional threads. Using relative path names in multithreaded applications or shared library code can yield unpredictable results and is not supported.

In WindowsВ 8 and Windows ServerВ 2012, this function is supported by the following technologies.

GetCurrentDir in a NT Service App

GetCurrentDir in a NT Service App

GetCurrentDir in a NT Service App

Hi, I’m programing a small NT Service app in Delphi 7, and I need to load an ini file in order to get some parameters, when I do for example:

an obviously put the ini file in that path every thing works fine, but I would like to get the ini file not from a fixed path in the code but from the same path where the myservice.exe es located, to do that I’ve try two metods that work fine in a normal app but for some reason do not in the service

ConfigIni:= TIniFile.Create(ExpandFileName(‘Config.ini’));
or
ConfigIni:= TIniFile.Create(GetCurrentDir+’Config.ini’);

any ideas why is this happening and of course how can I make this work.

RE: GetCurrentDir in a NT Service App

query the registry key :
‘\SYSTEM\CurrentControlSet\Services\’+ , look for the Imagepath string Value

——————————————————
What You See Is What You Get
Never underestimate tha powah of tha google!

Текст книги «Программирование в Delphi. Трюки и эффекты»

Это произведение, предположительно, находится в статусе ‘public domain’. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.

Автор книги: Александр Чиртик

Жанр: Программирование, Компьютеры

Текущая страница: 8 (всего у книги 24 страниц)

Для централизованного хранения временных данных, необходимых при работе приложений, в Windows предусмотрена специальная папка Temp. Ее расположение может изменяться. Причем в многопользовательских версиях Windows (NT, 2000, XP) местоположение папки для временных файлов может быть различным для различных пользователей. Итак, расположение папки Temp можно определить с помощью API-функции GetTempPath. Это функция принимает строковый буфер и длину этого буфера и возвращает количество символов, записанных в переданную строку, или 0, если возникла ошибка. Функция-оболочка, скрывающая работу со строковым буфером и преобразование типов, реализуется аналогично двум ранее рассмотренным функциям (листинг 4.12).

Листинг 4.12. Определение расположения папки временных файлов

function GetTempDir(): String;

SetLength(buffer, MAX_PATH + 1);

len:= GetTempPath(MAX_PATH, PAnsiChar(buffer));

Кроме того, Windows API предусматривает очень полезную функцию, избавляющую программиста от необходимости подбирать имена временным файлам так, чтобы они были уникальными в пределах заданной папки (это не обязательно должна быть папка Temp). Имя этой функции – GetTempFileName. Пример ее использования приведен в листинге 4.13.

Листинг 4.13. Определение имени временного файла

function GetTempFile (prefix: String= ‘

buffer, dir: String;

//Получение имени временного файла (система сама определяет имя,

//уникальное для заданной папки)

SetLength(buffer, MAX_PATH + 1);

GetTempFileName(PAnsiChar(dir), PAnsiChar(prefix), 0, PAnsiChar(buffer));

Приведенная в листинге 4.13 функция в качестве папки временных файлов использует папку Temp, однако функцию GetTempFileName можно использовать для получения имен файлов в пределах любой папки.

Кроме пути папки, в которой необходимо создать временный файл, функция GetTempFileName принимает строку-префикс для имени временного файла и целочисленное значение (третий параметр). Если третий параметр не равен нулю, то его значение в шестнадцатеричной форме просто прибавляется справа к строке prefix. Никаких проверок на уникальность получившегося имени файла при этом не производится. Если же третьему параметру присвоить значение 0, то система сама сформирует шестнадцатеричное значение так, чтобы имя файла было уникальным в заданной папке. При этом, кроме того, создается и сам файл.

Буфер (последний параметр функции GetTempFileName) должен вмещать как минимум MAX_PATH символов, так как функция записывает в него полный путь временного файла.

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

Рис. 4.2. Расположения папок WINDOWS, system, Temp и имя для временного файла

Определение прочих системных путей

В Windows существует ряд других системных путей, которые так или иначе могут пригодиться. Определяются они не менее просто, чем пути к системным папкам (листинг 4.14).

Листинг 4.14. Определение прочих системных путей

function GetSpecialDir(dirtype: Integer): String;

SetLength(buffer, MAX_PATH + 1);

SHGetSpecialFolderPath(0, PAnsiChar(buffer), dirtype, False);

Здесь используется функция командной оболочки файловой системы (Windows Shell) SHGetSpecialFolderPath, объявление которой находится в модуле ShlObj. Среди параметров этой функции самыми значимыми (кроме буфера длиной минимум MAX_PATH символов для помещения в него пути) являются два последних параметра. Третий параметр функции SHGetSpecialFolderPath используется для указания папки, расположение которой необходимо определить. Если четвертый параметр функции SHGetSpecialFolderPath не равен False и запрашиваемой папки не существует, то папка будет создана.

Пример использования функции GetSpesialDir для составления списка (в элементе управления ListView) некоторых системных путей приведен в листинге 4.15. Из него вы также можете узнать имена целочисленных констант, идентифицирующих некоторые папки.

Листинг 4.15. Использование функции GetSpecialDir

procedure TForm3.Button1Click(Sender: TObject);

//Определение путей некоторых системных папок

item.Caption:= ‘Рабочий стол’;

item.Caption:= ‘ Мои документы’;

item.Caption:= ‘Последние документы’;

item.Caption:= ‘ Авто загрузка ‘;

//..Папка с шаблонами документов

Пример возможного результата выполнения процедуры, представленной в листинге 4.14, показан на рис. 4.3.

Рис. 4.3. Прочие системные пути Windows

В коде приведенной в листинге 4.15 процедуры определены не все пути, доступные с использованием функции SHGetSpecialFolderPath. Дело в том, что существует ряд виртуальных (не существующих реально на диске) папок: Мой компьютер, Принтеры, Сетевое окружение и т. д.

Для некоторых упоминаемых в листинге 4.15 папок существуют также аналогичные папки, содержимое которых доступно всем пользователям:

• CSIDL_COMMON_DESKTOPDIRECTORY – содержимое этой папки отображается на Рабочем столе всех пользователей;

• CSIDL_COMMON_DOCUMENTS – содержит общие документы;

• CSIDL_COMMON_FAVORITES – содержит общие элементы папки Избранное;

• CSIDL_COMMON_PROGRAMS – содержит общие для всех пользователей программы (пункт Программы меню «Пуск»);

• CSIDL_COMMON_STARTMENU – содержит общие элементы, отображаемые в меню «Пуск»;

• CSIDL_COMMON_STARTUP – содержит общие элементы меню Автозагрузка;

• CSIDL_COMMON_TEMPLATES – папка с общими для всех пользователей шаблонами документов.

Большинство из перечисленных выше путей определяются только в системах Windows на ядре NT, но недоступны в Windows 95/98/Me.

Во время работы каждого приложения для него назначается папка, которая считается текущей (для этого приложения). При управлении текущей папкой удобно использовать рассмотренные ниже относительные пути.

Для определения текущей папки приложения используется функция GetCurrentDir, приведенная в листинге 4.16.

Листинг 4.16. Определение текущей папки

function GetCurrentDir(): String;

SetLength(buffer, MAX_PATH + 1);

len:= GetCurrentDirectory(MAX_PATH, PAnsiChar(buffer));

GetCurrentDir:= Copy(buffer, 1, len);

Функция определения пути текущей папки основана на применении соответствующей API-функции GetCurrentDirectory. Вполне естественно, что эта функция имеет себе пару – функцию для задания текущей папки SetCurrentDirectory. Объявление этой функции происходит следующим образом:

function SetCurrentDirectory(lpPathName: PChar): BOOL; stdcall;

Функция принимает путь папки и возвращает ненулевое значение в случае успешного своего выполнения.

Далее будет рассмотрено несколько функций, которые могут пригодиться, если возникнет необходимость преобразования путей. Имеется в виду прежде всего преобразование имен файлов в формат MS-DOS и обратно. Этот вид преобразования наглядно продемонстрирован на рис. 4.4 (верхняя часть формы).

Рис. 4.4. Преобразования путей

Иногда удобно представлять пути относительно какой-либо вложенной, а не корневой папки диска. Например, представьте, что вы разрабатываете приложение, документы которого, являющиеся неделимыми для пользователя, могут фактически состоять из большого количества файлов, расположенных в разных папках (Images, Movies, Embed и др.). Сами папки расположены в той же папке, что и основной файл документа или ниже по иерархии (во вложенных папках). Как добиться того, чтобы при копировании приложения со всеми нужными папками в другое место (на другой диск или компьютер, в другую папку) его по-прежнему можно было открыть, рассчитывая, что в папках Images, Movies и Embed содержится нужная информация. Для этого приложение должно «знать», какие файлы и в каких папках ему действительно необходимы. В таком случае пригодится относительный путь, который содержит в себе информацию о количестве и направлении переходов из папки, заданной в качестве корневой, чтобы можно было найти указанный в этом пути файл или папку.

Преобразование абсолютного пути в относительный и наоборот вы можете увидеть на рис. 4.4 (нижняя часть формы). Здесь в качестве исходного пути берется информация, содержащаяся в текстовом поле Исходный длинный путь, а в качестве пути папки для построения относительного пути – в текстовом поле Текущая папка.

На всякий случай стоит уточнить, что в относительном пути символ. указывает на текущую папку (никуда переходить не надо), а символ… означает папку, расположенную на один уровень выше (родительскую папку). Также следует уточнить, что под абсолютным путем понимается путь, корневым элементом которого является \ или :(C:, D: и т. д.).

Все приведенные далее функции преобразования вы можете найти в модуле PathConvert, расположенном на диске, в папке с названием подраздела.

Преобразование длинных имен файлов в короткие, и наоборот

Теперь рассмотрим реализацию преобразования путей. Сначала – преобразование между длинной и короткой формами. Выполняется это предельно просто (благо Windows API предусматривает соответствующие функции).

Функция преобразования длинного пути в короткий приведена в листинге 4.17.

Листинг 4.17. Преобразование длинного пути в короткую форму

function LongPathToShort(path: String): String;

len:= GetShortPathName(PAnsiChar(path), PAnsiChar(buffer), MAX_PATH);

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

Листинг 4.18. Преобразование пути из короткой в длинную форму

function ShortPathToLong(path: String): String;

len:= GetLongPathName(PAnsiChar(path), PAnsiChar(buffer), MAX_PATH);

При тестировании последнего листинга в Delphi 7 выяснилось, что API-функция GetLongPathName объявлена в модуле Windows. Возможно, в других версиях Delphi это не так, но, в любом случае, импортировать эту функцию из библиотеки Kernel32. dll предельно просто – достаточно поместить в модуль следующую строку:

function GetLongPathName(lpszLongPath: PChar; lpszShortPath: PChar;

cchBuffer: DWORD): DWORD; stdcall;

external kernel32 name ‘GetLongPathNameA’;

Преобразование абсолютного пути в относительный, и наоборот

Теперь пришла очередь рассмотреть реализацию преобразований между абсолютной и относительной формами путей. Однако сначала рассмотрим небольшую, но полезную процедуру, используемую при преобразованиях. Процедура GetPathElements (листинг 4.19) формирует список строк из компонентов переданного ей пути (имен папок и именицелевого файла или папки).

Листинг 4.19. Разбиение пути на составляющие

procedure GetPathElements(path: String; elements: TStrings);

start, pos: Integer;

for pos:= 1 to Length(path) do

if path [pos] = » then

if start <> pos then

//Выделим имя папки

elements.Add(Copy(path, start, pos – start))

//Сочетание типа ‘\’ в середине пути пропускаем

pos:= Length(path) + 1;

if start <> pos then

//Выделим имя последней папки или файла

elements.Add(Copy(path, start, pos – start));

После применения процедуры GetPathElements работать с компонентами пути становится достаточно удобно, да к тому же и упрощается код функций преобразования, так как при их написании не приходится уделять внимание, правильно ли выделены подстроки из строк полного пути.

Функция преобразования абсолютного пути в относительный (относительно заданной в параметре curdir папки) приведена в листинге 4.20.

Листинг 4.20. Преобразование абсолютного пути в относительный

function AbsPathToRelative(path, curdir: String): String;

pathElements, curElements: TStrings;

if Copy(path, 1, 2) <> Copy(curdir, 1, 2) then

//Папки на разных дисках

//Получение составляющих абсолютного и текущего пути

//Пропускаем одинаковые папки

else if pathElements[i] <> ‘.’ then

//Вниз по дереву (знак текущей папки «.» не изменяет положение)

//Формируем результирующий путь

if (curElements.Count > 0) then outPath:= curElements[0];

for i:= 1 to curElements.Count -1 do

out Path:= out Path + »+ curElements[i];

//Списки строк больше не нужны

Поиск является неотъемлемой частью работы с файловой системой. Даже простой просмотр содержимого любой папки сопряжен с использованием простейших, но все же поисковых средств (перебор и, возможно, отсеивание элементов папки). Поэтому далее будут рассмотрены возможные варианты реализации двух функций поиска: поиска по маске и атрибутам файлов в пределах заданной папки и такого же поиска по всему дереву папок, начиная от заданной корневой папки. Все рассмотренные далее функции поиска можно найти в модуле Search, расположенном на диске, в папке с названием подраздела.

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

Маски и атрибуты

Маска имени файла или папки представляет собой строку, в которой неизвестный одиночный символ можно заменять символом? а произвольное количество (0 и более) неизвестных заранее символов можно заменять символом *. Остальные (допустимые в имени) символы обозначают сами себя. Например, имена файлов SomeFile.exe и Some.exe удовлетворяют каждой из масок: Some* и Some*.exe.

Атрибуты определяют некоторые важные особенности файла. Так, например, при просмотре папки с помощью API-функций папка может отличаться от файла только наличием атрибута FILE_ATTRIBURE_DIRECTORY. Вообще содержимое папки записано на диске в самый обычный файл. Его отличает наличие указанного неизменяемого вручную атрибута и строго заданный формат записей, а также наличие специальных функций, скрывающих все особенности работы с данными папки (открытие файла с записями, поиск нужных записей).

Теперь об атрибутах. Ниже приведен перечень наиболее часто используемых атрибутов файлов и папок (идентификаторы целочисленных констант, объявленных в модуле Windows) (если не сказано иного, атрибут можно изменить):

• FILE_ATTRIBUTE_ARCHIVE – архивный файл или папка (на опыте замечено, что этот атрибут появляется практически у всех файлов, находящихся на диске некоторое время);

• FILE_ATTRI BUTE_DI RECTORY – атрибут папки (атрибут нельзя самостоятельно снять или назначить);

• FILE_ATTRIBUTE_HIDDEN – скрытый файл или папка;

• FILE_ATTRIBUTE_NORMAL – означает отсутствие особых атрибутов у файла или папки (у папки, естественно, всегда установлен атрибут FILE_ATTRIBUTE_ DIRECTORY);

• FILE_ATTRIBUTE_READONLY – файл или папка, доступные только для чтения;

• FILE_ATTRIBUTE_SYSTEM – системный файл или папка;

• FILE_ATTRIBUTE_TEMPORARY – временный файл (для ускорения доступа к находящимся в нем данным файловая система стремится по возможности хранить все содержимое открытого временного файла в оперативной памяти).

Выше были рассмотрены основные атрибуты, которые могут быть присвоены объектам файловой системы (файлам и папкам), но не было сказано, как получить или установить атрибуты файла или папки. Атрибуты можно получить при просмотре содержимого папки (как в рассмотренных далее функциях поиска), а также с помощью API-функции GetFileAttributes. Эта функция принимает путь файла (PChar) и возвращает значение типа DWORD (32-битное целое значение), представляющее собой битовую маску. Если функция GetFileAttributes завершается неудачно, то возвращаемое значение равно $FFFFFFFF (-1 при переводе к беззнаковому целому).

Каждому из рассмотренных атрибутов соответствует бит в возвращаемом функцией GetFileAttributes значении. Ниже приведен отрывок программы, определяющей, является ли файл системным:

var attrs: DWORD;

attrs:= GetFileAtt ribut e(PAnsiChar(‘C:boot.ini’));

if (attrs and FILE_ATTRIBUTE_SYSTEM <> 0) then <файл системный>;

Атрибуты устанавливаются с помощью API-функции SetFileAttributes. Данная функция принимает два параметра: путь файла или папки (PChar) и битовую маску атрибутов и возвращает ненулевое значение в случае успешного выполнения задачи и 0 (False) в противном случае.

Поскольку в функцию SetFileAttributes передается маска, хранящая сведения сразу обо всех атрибутах файла или папки, то изменять атрибуты нужно аккуратно (чтобы не удалить установленные ранее). Пример (отрывок программы) назначения одного и одновременного снятия другого атрибута файла приведен в листинге 4.22 (для простоты проверка ошибок не производится).

Листинг 4.22. Изменение атрибутов файла

var attrs: DWORD;

attrs:= GetFileAttributes(‘C:text .txt’);

attrs:= attrs or FILE_ATTRIBUTE_HIDDEN; //Установка атрибута «скрытый»

attrs:= attrs and not FILE_ATTRIBUTE_ARCHIVE; //Снятие атрибута «архивный»

Поиск в указанной папке

Поиск в пределах одной папки представляет собой простой перебор всех ее элементов с отбором тех, имена которых удовлетворяют маске и заданному набору атрибутов. В приведенном ниже примере (листинг 4.23) используется API-функция FindFirstFile, которая начинает просмотр указанной папки, автоматически отсеивая имена файлов и папок, не удовлетворяющие маске, и возвращает дескриптор (THandle), используемый для идентификации начатого сеанса просмотра папки при продолжении поиска (передается в функции FindNextFile и FindClose).

После окончания просмотра папки вызывается функция FindClose, завершающая просмотр папки. Весь процесс очень напоминает работу с обычным файлом (открытие, просмотр, закрытие), не так ли?

Листинг 4.23. Поиск в заданной папке

function SearchInFolder(folder, mask: String; flags: DWORD;

names: TStrings; addpath: Boolean = False): Boolean;

bRes: Boolean; //Если равен True, то найден хотя бы один файл или папка

strSearchPath:= folder + »+ mask;

hSearch:= FindFirstFile(PAnsiChar(strSearchPath), FindData);

if (hSearch <> INVALID_HANDLE_VALUE) then

//Ищем все похожие элементы (информация о первом элементе уже

//записана в FindData функцией FindFirstFile)

if (String(FindData.cFileName) <> ‘..’) and

(String(FindData.cFileName) <> ‘.’) then //Пропускаем . и ..

if MatchAttrs(flags, FindData.dwFileAttributes) then

//Нашли подходящий объект

if addpath then

until FindNextFile(hSearch, FindData) = False;

SearchInFolderr r:= bRes;

В результате работы функции SearchInFolder заполняется список names именами или, если значение параметра addpath равно True, полными путями найденных файлов и папок. Значение параметра flags (битовая маска атрибутов) формируется так же, как для функции SetFileAttributes, только одновременно могут быть установлены любые интересующие атрибуты. При обнаружении хотя бы одного файла или папки функция SearchlnFolder возвращает значение True.

В функции поиска проверка соответствия атрибутов найденных файлов и папок маске производится с помощью дополнительной функции MatchAttrs. Код этой функции приведен в листинге 4.24.

Листинг 4.24. Фильтр атрибутов

function MatchAttrs(flags, attrs: DWORD): Boolean;

MatchAttrs:= (flags and attrs) = flags;

Может показаться, что проверка из одной строки – недостаточная причина для создания отдельной функции. Тем не менее в рассматриваемом примере отдельная функция MatchAttrs выделена для того, чтобы сделать отсеивание файлов (и папок) по атрибутам более очевидным.

В листинге 4.24 приведена реализация нестрогого фильтра: он принимает файл или папку, если они имеют все установленные во flags атрибуты, независимо от того, имеет ли файл или папка дополнительные атрибуты. Так, если, например, задан flags:= FILE_ATTRIBUTE_READONLY, то будут найдены скрытые, системные и прочие как файлы, так и папки, имеющие среди своих атрибутов атрибут FILE_ATTRIBUTE_READONLY. Для реализации строгого фильтра можно заменить выражение в функции MatchAttrs простым равенством: flags = attrs.

Возможный результат поиска с использованием функции SearchInFolder показан на рис. 4.5.

Рис. 4.5. Поиск в заданной папке

Пример кода вызова функции SearchlnFolder (для показанного на рис. 4.5 приложения) приведен в листинге 4.25.

Листинг 4.25. Использование функции SearchlnFolder

//Запуск поиска файла в заданной папке

procedure TForm2.Button1Click(Sender: TObject);

//Формируем набор атрибутов (по установленным флажкам на форме)

if (chkDirs.Checked) then flags:= flags or FILE_ATTRIBUTE_DIRECTORY;

if (chkSystem.Checked) then flags:= flags or FILE_ATTRIBUTE_SYSTEM;

if (chkReadOnly.Checked) then flags:= flags or FILE_ATTRIBUTE_READONLY;

if (chkArchive.Checked) then flags:= flags or FILE_ATTRIBUTE_ARCHIVE;

//Поиск (файлы записываются прямо в список на форме)

if not SearchInFolder(txtFolder.Text, txtMask.Text, flags,

lblFound.Caption:= ‘Поиск не дал результатов’

lblFound.Caption:= ‘ Найдено объектов: ‘+ IntToStr(lstFiles.Count);

Поиск по всему дереву папок

В листинге 4.26 приведена одна из возможных реализаций рекурсивного поиска по дереву папок. Алгоритм поиска следующий.

1. Выполняется поиск в папке folder (все найденные файлы или папки добавляются в список names).

2. Функция SearchlnTree вызывается для каждой подпапки папки folder для продолжения поиска в поддереве, определяемом каждой подпапкой.

Листинг 4.26. Поиск по дереву папок

function SearchInTree(folder, mask: String; flags: DWORD;

names: TStrings; addpath: Boolean = False): Boolean;

bRes: Boolean; //Если равен True, то найден хотя бы один файл или папка

//Осуществляем пои ск в текущей папке

bRes:= SearchInFolder(folder, mask, flags, names, addpath);

//Продолжим поиск в каждой из подпапок

hSearch:= FindFirstFile(PAnsiChar(folder + ‘*’), FindData);

if (hSearch <> INVALID_HANDLE_VALUE) then

if (String(FindData.cFileName) <> ‘..’) and

(String(FindData.cFileName) <> ‘.’) then //Пропускаем . и ..

if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> 0)

//На йдена подпапка – выполним в ней поиск

if SearchInTree(folder + »+ String(FindData.cFileName),

mask, flags, names, addpath)

until FindNextFile(hSearch, FindData) = False;

В функции SearchInTree используется просмотр папки folder вручную (с помощью API-функций) из соображений эффективности. Если захотите, можете реализовать поиск подпапок с помощью функции SearchlnFolder. Правда, для этого придется завести дополнительный список (TStringList) для сохранения найденных в текущей папке подпапок. Элементы списка будут использоваться только один раз: для поиска в подпапках.

Возможный результат поиска с использованием функции SearchInTree приводится на рис. 4.6.

Рис. 4.6. Поиск по дереву папок

С небольшими изменениями алгоритм рекурсивного обхода дерева папок, реализованный в листинге 4.25, можно использовать и при операциях, отличных от простого поиска: например, при копировании или удалении дерева папок. Для этого достаточно выполнять нужные операции над каждым находимым объектом.

Это произведение, предположительно, находится в статусе ‘public domain’. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.

GetCurrentDir Routine

Description

(Please provide a description in your own words. It is illegal to use the wording from the Delphi Help.)

Technical Comments

(Known issues / Documentation clarifications / Things to be aware of)

Examples

(Please provide links to articles/source code that show how to use this item.)

See Also

(Please provide links to items specifically related to this item.)

User Comments/Tips

(Please leave your name with your comment.)

Беглый обзор модуля IOUtils.pas. Часть 1: работа с директориями в Delphi 2010.

С выходом версии 2010 в Delphi появился ещё один модуль — IOUtils.pas облегчающий работу с файлами и директориями. Признаться я просто катострофически не люблю работу с файлами в Delphi. Незнаю почему, но всегда напрягало реализовывать поиск по маске, чтение атрибутов и т.д. и т.п. Может из-за этого и решил рассмотреть, что же такого нового и облегчающего мою жизнь приготовили разработчики из Embarcadero.

Вначале обратимся к официальной Wiki Embarcadero и посмотрим, что там пишут про IOUtils:

…IOUtils contains three static classes: TDirectory, TPath and TFile. These classes expose a number of static methods useful for I/O tasks. …

Отлично. Всего три класса, содержащие ряд классовых методов. Начнем по порядку — с TDirectory.

Илон Маск рекомендует:  Что такое код fbsql_rollback
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL