Рейтинг@Mail.ru

System.IOUtils – удобные утилиты Delphi для работы с файлами и директориями

Автор: Alex. Опубликовано в Программирование . просмотров: 51881

Рейтинг:  5 / 5

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда активна
 

Начиная с версии XE2 в Delphi появился юнит System.IOUtils, включающий удобные утилиты для работы с файлами и директориями. Предлагаю вместе подробно разобраться с тем, что в юните System.IOUtils имеется и попробовать на примерах как это всё работает.

System.IOUtils – удобные утилиты Delphi для работы с файлами и директориями

Всего в юните System.IOUtils вы можете обнаружить три структуры TDirectory, TFile и TPath, содержащие только статические методы. Если вы разрабатываете на .NET, то вы заметите сходство этих трёх структур с классами Directory, File и Path из пространства имён System.IO в .NET. На самом деле в справке Delphi, так и написано, что большинство методов схожи с методами аналогичных классов в .NET. Это даже неплохо, ведь классы Directory, File и Path очень удобные, значит и в Delphi теперь всё должно быть удобно. Но давайте проверять.

Использование TDirectory

Структура TDirectory используется в Delphi для работы с директориями. Она содержит только статические методы. Давайте рассмотрим их.

Создание и удаление директории

Начнём наше знакомство со структурой TDirectory, пожалуй, с методов для создания и удаления директории. Для этого есть соответствующие методы CreateDirectory и Delete. Функция CreateDirectory принимает во входном параметре полный путь к директории и создаёт все недостающие в указанном пути папки. Например, если вы хотите создать директорию «Test3», путь к которой должен быть «C:\Test1\Test2\Test3», а у вас на компьютере есть только директория «C:\Test1», которой нет директории «Test2», то функция CreateDirectory создаст сначала директорию «Test2» в директории «Test1», а затем создаст директорию «Test3» в директории «Test2». Т.е. после вызова этой функции у вас будут все три директории, указанные в пути.

Функция Delete удаляет только последнюю директорию, указанную в пути. Например, если у вас на диске «C:» есть директория «Test1», в ней директория «Test2», и в ней директория «Test3», то чтобы удалить директорию «Test3» в функцию Delete нужно передать полный путь к этой директории, в нашем примере это будет «C:\Test1\Test2\Test3». Также функция Delete умеет рекурсивно удалять вложенные директории и файлы, если второй входной параметр установлен в true.

Вот примеры использования функций CreateDirectory и Delete:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Создаём директории Test1, Test2 и Test3, если их нет.
        TDirectory.CreateDirectory('C:\Test1\Test2\Test3');
        //Удаляем директорию Test3.
        TDirectory.Delete('C:\Test1\Test2\Test3');
        try
            //Удаляем директорию Test1.
            //Директория Test1 не пустая, т.к. в ней есть директория Test2.
            //Поэтому при вызове метода Delete произойдёт ошибка EInOutError.
            TDirectory.Delete('C:\Test1');
        except
            on ioError: EInOutError do
                //Показываем ошибку в консоли.
                Writeln(ErrOutput, ioError.Message);
        end;
        //Удаляем директорию Test1 и рекурсивно все вложенные директории и файлы.
        TDirectory.Delete('C:\Test1', true);
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Проверка существования директории

Чтобы проверить, существует ли директория, у структуры TDirectory есть функция Exists. Первый параметр функции – это путь к директории. Второй необязательный параметр FollowLink учитывается только при использовании символической ссылки. Если нужно проверить только существование символической ссылки на директорию, то нужно установить этот параметр в false, а если нужно проверить наличие всего сразу, т.е. и символической ссылки на директорию и самой директории, то нужно установить этот параметр в true. Вот примеры использования:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Shellapi, Classes, Windows;
var
    execInfo: TShellExecuteInfo;
 
begin
    try
        //Проверяем, есть ли директория C:\Test1.
        //Если директории нет, то функция вернёт false.
        Writeln(TDirectory.Exists('C:\Test1'));
 
        //Создаём директорию.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Ещё раз проверяем, есть ли директория C:\Test1.
        //Теперь директория существует, и функция вернёт true.
        Writeln(TDirectory.Exists('C:\Test1'));
 
        //Теперь проверяем, существует ли символическая ссылка C:\TestLink.
        //Если ссылка не существует, то функция вернёт false.
        Writeln(TDirectory.Exists('C:\TestLink', false));
 
        //Теперь создадим символическую ссылку C:\TestLink на несуществующую директорию C:\Test2.
        //Для создания символической ссылки нужно обладать правами администратора,
        //поэтому создавать её будем с помощью утилиты командной строки mklink,
        //которую будем вызывать от имени администратора.
        //Чтобы вызвать эту утилиту, придётся сначала создать пакетный файл,
        //а затем выполнить его.
        //Итак, сначала создаём пакетный файл с командой mklink.
        with TStringList.Create do
            try
                //Содержимое пакетного файла...
                Add('mklink /D C:\TestLink C:\Test2');
                //Сохраняем пакетный файл.
                SaveToFile('C:\Test1\tmp.bat');
            finally
                Free;
            end;
        //Теперь выполняем пакетный файл от имени администратора.
        FillChar(execInfo, SizeOf(TShellExecuteInfo), 0);
        execInfo.cbSize := SizeOf(TShellExecuteInfo);
        execInfo.lpVerb := PWideChar('runas');
        execInfo.lpFile := PWideChar('C:\Test1\tmp.bat');
        execInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
        ShellExecuteEx(@execInfo);
        //Ждём, пока пакетный файл отработает.
        WaitForSingleObject(execInfo.hProcess, INFINITE);
 
        //Проверяем, существует ли символическая ссылка C:\TestLink.
        //Теперь ссылка существует, поэтому функция вернёт true.
        Writeln(TDirectory.Exists('C:\TestLink', false));
 
        //Проверяем, существует ли символическая ссылка C:\TestLink
        //и директория C:\Test2, на которую она ссылается.
        //Ссылка C:\TestLink существует, но директория C:\Test2 - нет,
        //поэтому функция вернёт false.
        Writeln(TDirectory.Exists('C:\TestLink', true));
 
        //Создаём директорию C:\Test2.
        TDirectory.CreateDirectory('C:\Test2');
 
        //Опять проверяем, существует ли символическая ссылка C:\TestLink
        //и директория C:\Test2, на которую она ссылается.
        //Теперь ссылка C:\TestLink и директория C:\Test2 существуют,
        //поэтому функция вернёт true.
        Writeln(TDirectory.Exists('C:\TestLink', true));
 
        //Удаляем директорию C:\Test1, а заодно и файл tmp.bat.
        TDirectory.Delete('C:\Test1', true);
        //Удаляем директорию C:\Test2.
        TDirectory.Delete('C:\Test2');
        //Удаляем символическую ссылку C:\TestLink.
        DeleteFile('C:\TestLink');
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Чтение и изменение характеристик директории

В структуре TDirectory для чтения и изменения характеристик директории есть следующие методы:

        • GetAttributes – возвращает атрибуты папки, такие как «только чтение», «системная», «скрытая» и т.п.;
        • SetAttributes – устанавливает новый набор атрибутов директории, такие как «только чтение», «системная», «скрытая» и т.п.;
        • GetCreationTime и GetCreationTimeUtc – возвращают дату и время создания директории;
        • SetCreationTime и SetCreationTimeUtc – устанавливают дату и время создания директории;
        • GetLastAccessTime и GetLastAccessTimeUtc – возвращают дату и время последнего обращения к директории;
        • SetLastAccessTime и SetLastAccessTimeUtc – устанавливают дату и время последнего обращения к директории;
        • GetLastWriteTime и GetLastWriteTimeUtc – возвращают дату и время последней записи в директорию.
        • SetLastWriteTime и SetLastWriteTimeUtc – устанавливают дату и время последней записи в директорию.

Функции, возвращающие и устанавливающие время, в конце имени которых есть суффикс «Utc», возвращают время в формате всемирного координированного времени (UTC).

Теперь рассмотрим примеры:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Rtti;
var
    fileAttribute: TFileAttribute;
 
begin
    try
        //Создаём директории Test1, Test2 и Test3, если их нет.
        TDirectory.CreateDirectory('C:\Test1\Test2\Test3');
 
        //Делаем директорию скрытой, выставляя ей атрибут faHidden.
        TDirectory.SetAttributes('C:\Test1', [TFileAttribute.faHidden]);
        //Делаем директорию доступной только для чтения, выставляя ей атрибут faReadOnly.
        TDirectory.SetAttributes('C:\Test1\Test2\Test3', [TFileAttribute.faReadOnly]);
        //Отображаем все установленные атрибуты директории Test1.
        //В результате отобразятся два атрибута: faHidden и faDirectory.
        //Атрибут faDirectory убрать нельзя, он всегда будет присутствовать у директории.
        for fileAttribute in TDirectory.GetAttributes('C:\Test1') do
            Writeln(TRttiEnumerationType.GetName<TFileAttribute>(fileAttribute));
        //Отображаем все установленные атрибуты директории Test3.
        //В результате отобразятся два атрибута: faReadOnly и faDirectory.
        for fileAttribute in TDirectory.GetAttributes('C:\Test1\Test2\Test3') do
            Writeln(TRttiEnumerationType.GetName<TFileAttribute>(fileAttribute));
 
        //Выводим дату и время создания директории Test1.
        //В результате отобразится дата и время на момент создания директории.
        Writeln(DateTimeToStr(TDirectory.GetCreationTime('C:\Test1')));
        //Устанавливаем дату и время создания директории.
        TDirectory.SetCreationTime('C:\Test1', StrToDateTime('01.02.03 11:12:13'));
        //Выводим дату и время создания директории Test1.
        //В результате отобразится 01.02.2003 11:12:13.
        Writeln(DateTimeToStr(TDirectory.GetCreationTime('C:\Test1')));
        //Выводим дату и время создания директории Test1 в формате UTC, т.е. без учёта часового пояса.
        //В результате отобразится 01.02.2003 8:12:13, т.е. -3 часа по Москве.
        Writeln(DateTimeToStr(TDirectory.GetCreationTimeUtc('C:\Test1')));
 
        //Выводим дату и время последнего обращения к директории.
        Writeln(DateTimeToStr(TDirectory.GetLastAccessTime('C:\Test1')));
        //Устанавливаем дату и время последнего обращения к директории.
        TDirectory.SetLastAccessTime('C:\Test1', StrToDateTime('01.02.03 11:12:14'));
        //Выводим дату и время последнего обращения к директории.
        //В результате отобразится 01.02.2003 11:12:14.
        Writeln(DateTimeToStr(TDirectory.GetLastAccessTime('C:\Test1')));
 
        //Выводим дату и время последней записи в директорию.
        Writeln(DateTimeToStr(TDirectory.GetLastWriteTime('C:\Test1')));
        //Устанавливаем дату и время последней записи в директорию.
        TDirectory.SetLastWriteTime('C:\Test1', StrToDateTime('01.02.03 11:12:15'));
        //Выводим дату и время последней записи в директорию.
        //В результате отобразится 01.02.2003 11:12:15.
        Writeln(DateTimeToStr(TDirectory.GetLastWriteTime('C:\Test1')));
 
        //Удаляем директорию Test1 и рекурсивно все вложенные директории и файлы.
        TDirectory.Delete('C:\Test1', true);
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Копирование, перемещение и переименование директории

Для копирования директории у структуры TDirectory есть метод Copy, а для перемещения или переименования – метод Move. Перечисленные выше операции производятся с директорией в целом, включая вложенные директории и файлы.

Если директория, в которую происходит копирование, уже существует, то произойдёт слияние существующей директории и директории, которую вы копируете. При этом совпадающие файлы в директории назначения будут удалены, а вместо них будут скопированы файлы из директории источника.

Вот пример использования методов Copy и Move:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Создаём директории Test1, Test2 и Test3, если их нет.
        TDirectory.CreateDirectory('C:\Test1\Test2\Test3');
 
        //Копируем директорию Test1 в директорию Test1.1, включая все вложенные директории и файлы.
        TDirectory.Copy('C:\Test1', 'C:\Test1.1');
 
        //Переименовываем директорию Test1 в директорию Test1.2.
        TDirectory.Move('C:\Test1', 'C:\Test1.2');
 
        //Перемещаем директорию Test1.2 в директорию C:\Users\Public\Documents.
        TDirectory.Move('C:\Test1.2', 'C:\Users\Public\Documents\Test1.2');
 
        //Удаляем директории.
        TDirectory.Delete('C:\Test1.1', true);
        TDirectory.Delete('C:\Users\Public\Documents\Test1.2', true);
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Получение списка файлов и поддиректорий в директории

Чтобы получить список всех файлов и поддиректорий, находящихся внутри какой-либо директории у структуры TDirectory есть методы GetFiles, GetDirectories и GetFileSystemEntries. Метод GetFiles возвращает только файлы, метод GetDirectories – только поддиректории, метод GetFileSystemEntries возвращает и файлы и директории. Каждый из этих методов поддерживает шаблоны поиска и фильтры и может работать рекурсивно.

Кроме того здесь стоит упомянуть и о функции IsEmpty, которая проверяет, пустая директория или нет.

Вот примеры использования методов GetFiles, GetDirectories, GetFileSystemEntries и IsEmpty:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Types, DateUtils;
var
    s: string;
 
    function FilterBySize(const Path: string;
            const SearchRec: TSearchRec): boolean;
    begin
        //Возвращаем true, если размер файла меньше 50 Кбайт.
        Result := SearchRec.Size < 51200;
    end;
 
    function FilterByDateTime(const Path: string;
            const SearchRec: TSearchRec): boolean;
    begin
        //Возвращаем true, если у файла или директории
        //дата и время последнего изменения старше 2-х лет.
        Result := SearchRec.TimeStamp < IncYear(Now, -2);
    end;
 
begin
    try
 
        //Ищеи и отображаем все файлы в директории C:\Windows.
        for s in TDirectory.GetFiles('C:\Windows') do
            Writeln(s);
 
        //Ищем и отображаем все исполняемые файлы в директории C:\Windows.
        for s in TDirectory.GetFiles('C:\Windows', '*.exe') do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все файлы
        //в директории C:\Users\Public\Pictures.
        for s in TDirectory.GetFiles('C:\Users\Public\Pictures', '*',
                TSearchOption.soAllDirectories) do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все файлы с расширением .jpg
        //в директории C:\Users\Public\Pictures.
        for s in TDirectory.GetFiles('C:\Users\Public\Pictures', '*.jpg',
                TSearchOption.soAllDirectories) do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все файлы размером меньше 50 Кбайт
        //в директории C:\Users\Public\Pictures.
        //Для проверки размера используется функция-фильтр FilterBySize.
        for s in TDirectory.GetFiles('C:\Users\Public\Pictures', '*',
                TSearchOption.soAllDirectories, FilterBySize) do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все файлы
        //в директории C:\Users\Public\Pictures, которые не изменялись более 2-х лет.
        //Для проверки размера используется функция-фильтр FilterByDateTime.
        for s in TDirectory.GetFiles('C:\Users\Public\Pictures', '*',
                TSearchOption.soAllDirectories, FilterByDateTime) do
            Writeln(s);
 
        //Ищем и отображаем все поддиректории в директории C:\Windows.
        for s in TDirectory.GetDirectories('C:\Windows') do
            Writeln(s);
 
        //Ищем и отображаем все поддиректории, имя которых начинается с буквы s,
        //в директории C:\Windows.
        for s in TDirectory.GetDirectories('C:\Windows', 's*') do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все поддиректории
        //в директории C:\Users\Public\Pictures.
        for s in TDirectory.GetDirectories('C:\Users\Public\Pictures', '*',
                TSearchOption.soAllDirectories) do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все поддиректории
        //в директории C:\Users\Public\Pictures, которые не изменялись более 2-х лет.
        //Для проверки размера используется функция-фильтр FilterByDateTime.
        for s in TDirectory.GetDirectories('C:\Users\Public\Pictures', '*',
                TSearchOption.soAllDirectories, FilterByDateTime) do
            Writeln(s);
 
        //Ищем и отображаем все файлы и поддиректории в директории C:\Windows.
        for s in TDirectory.GetFileSystemEntries('C:\Windows') do
            Writeln(s);
 
        //Ищем и отображаем все файлы и поддиректории,
        //имя которых начинается с буквы s, в директории C:\Windows.
        for s in TDirectory.GetFileSystemEntries('C:\Windows', 's*') do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все файлы и поддиректории
        //в директории C:\Users\Public\Pictures.
        for s in TDirectory.GetFileSystemEntries('C:\Users\Public\Pictures',
                TSearchOption.soAllDirectories, nil) do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все файлы и поддиректории
        //в директории C:\Users\Public\Pictures, которые не изменялись более 2-х лет.
        //Для проверки размера используется функция-фильтр FilterByDateTime.
        for s in TDirectory.GetFileSystemEntries('C:\Users\Public\Pictures',
                TSearchOption.soAllDirectories, FilterByDateTime) do
            Writeln(s);
 
        //Рекурсивно ищем и отображаем все пустые поддиректории
        //в директории C:\Users\Public\Pictures.
        for s in TDirectory.GetDirectories('C:\Users\Public\Pictures', '*',
                TSearchOption.soAllDirectories) do
            if TDirectory.IsEmpty(s) then
                Writeln(s);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Работа с путями директорий

Путь, который определяет местоположение директории, может сказать о многом. Из него, например, можно получить корневую директорию с помощью функции GetDirectoryRoot. В нём можно найти все родительские директории с помощью рекурсивного вызова функции GetParent. Иногда путь может быть относительным, что вы сможете легко проверить с помощью функции IsRelativePath.

Дополнительно может пригодиться функция GetLogicalDrives, возвращающая список всех логических дисков на компьютере.

Вот примеры использования этих функций:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
var
    s: string;
 
begin
    try
 
        //Узнаём корневую директорию для директории C:\Users\Public\Pictures.
        //В результате мы получим 'C:\'.
        Writeln(TDirectory.GetDirectoryRoot('C:\Users\Public\Pictures'));
 
        //Узнаём корневую директорию для сетевой папки \\my-server\Shared\Music.
        //В результате мы получим '\\my-server\Shared'.
        Writeln(TDirectory.GetDirectoryRoot('\\my-server\Shared\Music'));
 
        //Узнаём корневую директорию для сетевой папки \\192.168.1.100\Shared\Docs.
        //В результате мы получим '\\192.168.1.100\Shared'.
        Writeln(TDirectory.GetDirectoryRoot('\\192.168.1.100\Shared\Docs'));
 
        //Рекурсивно выводим все родительские директории
        //для директории C:\Users\Public\Pictures.
        //В результате мы получим:
        //'C:\Users\Public'
        //'C:\Users'
        //'C:\'
        s := 'C:\Users\Public\Pictures';
        while not TDirectory.GetParent(s).IsEmpty do
        begin
            s := TDirectory.GetParent(s);
            Writeln(s);
        end;
 
        //Узнаём, является ли путь относительным.
        //В результате получим FALSE.
        Writeln(TDirectory.IsRelativePath('C:\Users\Public\Pictures'));
        //В результате получим TRUE.
        Writeln(TDirectory.IsRelativePath('.\Public\Pictures'));
        //В результате получим TRUE.
        Writeln(TDirectory.IsRelativePath('..\Shared\Music'));
 
        //Узнаём, какие логические диски есть на ПК.
        //Если у вас три диска C:, D: и F:, то результат будет таким:
        //'C:\'
        //'D:\'
        //'F:\'
        for s in TDirectory.GetLogicalDrives do
            Writeln(s);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Получение и изменение текущей директории приложения

Кроме всего вышеперечисленного у структуры TDirectory есть функции для получения и изменения текущей директории приложения: GetCurrentDirectory и SetCurrentDirectory. Вот примеры использования:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
var
    s: string;
 
begin
    try
        //Получаем тукущую директорию приложения.
        Writeln(TDirectory.GetCurrentDirectory);
 
        //Задаём другую текущую директорию приложения.
        TDirectory.SetCurrentDirectory('C:\Users\Public\Pictures');
 
        //Ещё раз получаем тукущую директорию приложения.
        //Теперь это будет C:\Users\Public\Pictures.
        Writeln(TDirectory.GetCurrentDirectory);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Использование TFile

Структура TFile используется в Delphi для работы с файлами. Она содержит только статические методы. Давайте рассмотрим их.

Создание и удаление файла

Для создания файла у структуры TFile есть несколько методов:

        • Create – создаёт пустой файл и возвращает ассоциированный с ним поток (экземпляр TFileStream), в который сразу можно записывать какие-либо данные.
        • CreateText – создаёт пустой файл и возвращает экземпляр объекта TStreamWriter для записи текста в файл.
        • CreateSymLink – создаёт символическую ссылку (которая, по сути, тоже является файлом) для папки или файла. Обратите внимание, что для создания символической ссылки, ваше приложение должно выполняться с правами администратора.

Для удаления файла есть функция Delete.

Рассмотрим примеры:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Classes;
var
    fileStream: TFileStream;
    bytes: TBytes;
    streamWriter: TStreamWriter;
 
begin
    try
        //Создаём временную директорию.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Создаём файл test.dat.
        fileStream := TFile.Create('C:\Test1\test.dat');
        try
            bytes := [1, 2, 3];
            //Записываем в файл данные из массива bytes.
            fileStream.Write(bytes, Length(bytes));
        finally
            //Удаляем поток.
            fileStream.Free;
        end;
 
        //Удаляем файл test.dat.
        TFile.Delete('C:\Test1\test.dat');
 
        //Создаём текстовый файл test.txt.
        streamWriter := TFile.CreateText('C:\Test1\test.txt');
        try
            //Записываем текст.
            streamWriter.Write('Здравствуй, мир!');
        finally
            //Удаляем писателя.
            streamWriter.Free;
        end;
 
        //Удаляем файл test.txt.
        TFile.Delete('C:\Test1\test.txt');
 
        //Создаём символическую ссылку.
        if not TFile.CreateSymLink('C:\Test1\test', 'C:\Test1\test.txt') then
            //Если символическая ссылка не создалась, выдаём ошибку.
            RaiseLastOSError;
 
        //Удаляем символическую ссылку test.
        TFile.Delete('C:\Test1\test');
 
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
 
    //Удаляем директорию.
    TDirectory.Delete('C:\Test1');
 
    Readln;
end.

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

У структуры TFile есть очень удобные методы, позволяющие делать запись в файл и чтение из него, всего в одну строчку. Вот эти методы:

        • WriteAllBytes – записывает массив байт в файл. Если указанный файл существует, то он будет перезаписан.
        • WriteAllLines – записывает все строки из массива строк в файл. Если указанный файл существует, то он будет перезаписан. Метод умеет конвертировать записываемый текст в нужную кодировку. Если указана кодировка и она не ANSI, то метод записывает маркер последовательности байтов (BOM).
        • WriteAllText – записывает одну строку в файл. Если указанный файл существует, то он будет перезаписан. Метод умеет конвертировать записываемый текст в нужную кодировку. Также метод умеет записывать маркер последовательности байтов (BOM).
        • AppendAllText – добавляет текст в конец файла. Если файла нет, то он будет создан.
        • ReadAllBytes – считывает файл в новый массив байт.
        • ReadAllLines – считывает все строки из файла в массив строк. Метод умеет считывать текст в заданной кодировке.
        • ReadAllText – считывает весь текст из файла. Метод умеет считывать текст в заданной кодировке.

Вот примеры использования методов WriteAllText, ReadAllText и AppendAllText:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Types;
 
begin
    try
        //Создаём директорию C:\Test1.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Записываем текст в файл в кодировке UTF-8 без BOM.
        TFile.WriteAllText('C:\Test1\test.txt', 'Тест!');
 
        //Считываем текст из файла.
        //В результате мы увидим 'РўРчС?С'!', т.к. текст считался в неправильной кодировке.
        //Это происходит из-за того, что файл записан в кодировке UTF-8,
        //и т.к. BOM отсутствует, то при считывании используется кодировка ANSI.
        Writeln(TFile.ReadAllText('C:\Test1\test.txt'));
 
        //Считываем текст из файла и укажем нужную кодировку.
        //В результате мы увидим 'Тест!', т.е. теперь текст считался в правильной кодировке.
        Writeln(TFile.ReadAllText('C:\Test1\test.txt', TEncoding.UTF8));
 
        //Теперь записываем текст в файл в кодировке ANSI, в которой локаль зависит
        //от выставленной локали на вашем компьютере.
        //При записи в этой кодировке, файл запишется без BOM.
        TFile.WriteAllText('C:\Test1\test.txt', 'Тест!', TEncoding.ANSI);
 
        //Считываем текст из файла.
        //В результате мы увидим 'Тест!'. В файле нет BOM,
        //поэтому файл считывается в кодировке ANSI,
        //т.е. как раз в той, в которой мы его записали.
        Writeln(TFile.ReadAllText('C:\Test1\test.txt'));
 
        //Теперь записываем текст в файл в кодировке UTF-8 с BOM.
        TFile.WriteAllText('C:\Test1\test.txt', 'Тест!', TEncoding.UTF8);
 
        //Считываем текст из файла.
        //В результате мы увидим 'Тест!'.
        //В отличие от первого примера здесь кодировка берётся из BOM,
        //т.е. в нашем случае UTF-8, поэтому текст считывается корректно.
        Writeln(TFile.ReadAllText('C:\Test1\test.txt'));
 
        //Добавляем в конец файла текст.
        //При добавлении будет использована кодировка, указанная в BOM.
        //Если BOM нет, то будет использована кодировка ANSI.
        TFile.AppendAllText('C:\Test1\test.txt', ' Тест2!');
 
        //Считываем текст из файла.
        //В результате мы увидим 'Тест! Тест2!'.
        Writeln(TFile.ReadAllText('C:\Test1\test.txt'));
 
        //Удаляем директорию C:\Test1 и все файлы в ней.
        TDirectory.Delete('C:\Test1', true);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Вот примеры использования методов WriteAllLines, ReadAllLines и AppendAllText:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Types;
var
    s: string;
 
begin
    try
        //Создаём директорию C:\Test1.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Записываем три строки в текстовый файл в кодировке UTF-8 без BOM.
        TFile.WriteAllLines('C:\Test1\test2.txt',
                ['Строка 1', 'Строка 2', 'Строка 3']);
 
        //Читаем строки из файла. В результате получим:
        //РЎС'С?Р?РєР° 1
        //РЎС'С?Р?РєР° 2
        //РЎС'С?Р?РєР° 3
        //Как видим строки считываются в неправильной кодировке.
        //Это происходит из-за того, что файл записан в кодировке UTF-8,
        //и т.к. BOM отсутствует, то при считывании используется кодировка ANSI.
        for s in TFile.ReadAllLines('C:\Test1\test2.txt') do
            Writeln(s);
 
        //Теперь читаем строки из файла в нужной кодировке. Результат будет:
        //Строка 1
        //Строка 2
        //Строка 3
        for s in TFile.ReadAllLines('C:\Test1\test2.txt', TEncoding.UTF8) do
            Writeln(s);
 
        //Теперь записываем строки в файл в кодировке ANSI, в которой локаль зависит
        //от выставленной локали на вашем компьютере.
        //При записи в этой кодировке, файл запишется без BOM.
        TFile.WriteAllLines('C:\Test1\test2.txt',
                ['Строка 1', 'Строка 2', 'Строка 3'], TEncoding.ANSI);
 
        //Ещё раз считываем строки из файла. В результате получим:
        //Строка 1
        //Строка 2
        //Строка 3
        //В файле нет BOM, поэтому файл считывается в кодировке ANSI,
        //т.е. как раз в той, в которой мы его записали.
        for s in TFile.ReadAllLines('C:\Test1\test2.txt') do
            Writeln(s);
 
        //Теперь записываем строки в файл в кодировке UTF-8 с BOM.
        TFile.WriteAllLines('C:\Test1\test2.txt',
                ['Строка 1', 'Строка 2', 'Строка 3'], TEncoding.UTF8);
 
        //Считываем строки из файла. В результате увидим:
        //Строка 1
        //Строка 2
        //Строка 3
        //В отличие от первого примера здесь кодировка берётся из BOM,
        //т.е. в нашем случае UTF-8, поэтому строки считываются корректно.
        for s in TFile.ReadAllLines('C:\Test1\test2.txt') do
            Writeln(s);
 
        //Добавляем в конец файла ещё две строки (строки разделяются символами #13#10).
        //При добавлении будет использована кодировка, указанная в BOM.
        //Если BOM нет, то будет использована кодировка ANSI.
        TFile.AppendAllText('C:\Test1\test2.txt', 'Строка 4'#13#10'Строка 5'#13#10);
 
        //Считываем строки из файла. В результате увидим:
        //Строка 1
        //Строка 2
        //Строка 3
        //Строка 4
        //Строка 5
        for s in TFile.ReadAllLines('C:\Test1\test2.txt') do
            Writeln(s);
 
        //Удаляем директорию C:\Test1 и все файлы в ней.
        TDirectory.Delete('C:\Test1', true);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

А вот примеры использования функций WriteAllBytes и ReadAllBytes:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Types;
var
    b: byte;
 
begin
    try
        //Создаём директорию C:\Test1.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Записываем массив из четырёх байт в файл.
        TFile.WriteAllBytes('C:\Test1\test.dat', [0, 100, 200, 255]);
 
        //Считываем байты из файла. В результате увидим в консоли:
        //0
        //100
        //200
        //255
        for b in TFile.ReadAllBytes('C:\Test1\test.dat') do
            Writeln(b);
 
        //Удаляем директорию C:\Test1 и все файлы в ней.
        TDirectory.Delete('C:\Test1', true);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Ещё несколько функций для того, чтобы открыть файл

Теперь рассмотрим ещё на несколько удобных функций для открытия файла. Это функции AppendText, OpenText, Open, OpenRead, OpenWrite.

Функции AppendText и OpenText предназначены для работы с текстовыми файлами в кодировке UTF-8. AppendText открывает файл, или создаёт новый файл, если его не было, для добавления в него текста, а OpenText – для чтения из текстового файла. Функция AppendText для работы с файлом, создаёт и возвращает объект TStreamWriter, который после использования нужно удалить. Функция OpenText для чтения текста создаёт и возвращает объект TStreamReader, который после использования также нужно удалить.

Функции Open, OpenRead, OpenWrite по сути просто создают объект TFileStream и возвращают его. Функция OpenRead открывает файл на чтение, функция OpenWrite - на запись, а функция Open может, как создавать файлы, так и открывать их в различных режимах и с различными привилегиями.

Рассмотрим примеры использования этих функций:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Classes;
 
var
    streamWriter: TStreamWriter;
    streamReader: TStreamReader;
    fileStream: TFileStream;
    bytes: TBytes;
    b: byte;
 
begin
    try
        //Создаём временную директорию.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Создаём текстовый файл test.txt в кодировке UTF-8 и добавляем в две строки текста.
        streamWriter := TFile.AppendText('C:\Test1\test.txt');
        try
            streamWriter.Write('Привет, мир!');
            streamWriter.WriteLine;
            streamWriter.Write('Это вторая строка в тексте.');
        finally
            streamWriter.Free;
        end;
 
        //Открываем текстовый файл в кодировке UTF-8 на чтение, и считываем две строки текста.
        streamReader := TFile.OpenText('C:\Test1\test.txt');
        try
            Writeln('1-я строка: ' + streamReader.ReadLine);
            Writeln('2-я строка: ' + streamReader.ReadLine);
        finally
            streamReader.Free;
        end;
 
        //Создаём файл функцией Open и записываем 3 байта.
        fileStream := TFile.Open('C:\Test1\test.dat', TFileMode.fmCreate, TFileAccess.faWrite);
        try
            bytes := [10, 20, 30];
            fileStream.Write(bytes, 3);
        finally
            fileStream.Free;
        end;
 
        //Дописываем в файл ещё 3 байта функцией OpenWrite.
        fileStream := TFile.OpenWrite('C:\Test1\test.dat');
        try
            bytes := [40, 50, 60];
            fileStream.Seek(0, TSeekOrigin.soEnd);
            fileStream.Write(bytes, 3);
        finally
            fileStream.Free;
        end;
 
        //Читаем из файла все байты функцией OpenRead.
        fileStream := TFile.OpenRead('C:\Test1\test.dat');
        try
            SetLength(bytes, fileStream.Size);
            fileStream.Read(bytes, fileStream.Size);
            for b in bytes do
                Writeln(b);
        finally
            fileStream.Free;
        end;
 
        //Удаляем директорию C:\Test1 и все файлы в ней.
        TDirectory.Delete('C:\Test1', true);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

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

Так же как и у TDirectory у структуры TFile есть функция Exists. Первый параметр функции – это путь к файлу. Второй необязательный параметр FollowLink учитывается только при использовании символической ссылки. Если нужно проверить только существование символической ссылки на файл, то нужно установить этот параметр в false, а если нужно проверить наличие всего сразу, т.е. и символической ссылки на файл и самого файла, то нужно установить этот параметр в true. Вот примеры использования:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, ShellAPI, Classes, Windows;
var
    execInfo: TShellExecuteInfo;
 
begin
    try
        //Проверяем, есть ли файл.
        //Если файла нет, то функция вернёт false.
        Writeln(TFile.Exists('C:\Test1\test1.txt'));
 
        //Создаём директорию C:\Test1.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Создаём файл test.txt.
        TFile.CreateText('C:\Test1\test1.txt').Free;
 
        //Проверяем, есть ли файл ещё раз.
        //Теперь файл точно есть, поэтому функция вернёт true.
        Writeln(TFile.Exists('C:\Test1\test1.txt'));
 
        //Теперь проверяем, существует ли символическая ссылка C:\Test1\TestLink.
        //Если ссылка не существует, то функция вернёт false.
        Writeln(TFile.Exists('C:\Test1\TestLink', false));
 
        //Создадим символическую ссылку C:\Test1\TestLink на несуществующий файл C:\Test1\test2.txt.
        //Для создания символической ссылки нужно обладать правами администратора,
        //поэтому создавать её будем с помощью утилиты командной строки mklink,
        //которую будем вызывать от имени администратора.
        //Чтобы вызвать эту утилиту, придётся сначала создать пакетный файл,
        //а затем выполнить его.
        //Итак, сначала создаём пакетный файл с командой mklink.
        TFile.WriteAllText('C:\Test1\tmp.bat', 'mklink C:\Test1\TestLink C:\Test1\test2.txt');
        //Теперь выполняем пакетный файл от имени администратора.
        FillChar(execInfo, SizeOf(TShellExecuteInfo), 0);
        execInfo.cbSize := SizeOf(TShellExecuteInfo);
        execInfo.lpVerb := PWideChar('runas');
        execInfo.lpFile := PWideChar('C:\Test1\tmp.bat');
        execInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
        ShellExecuteEx(@execInfo);
        //Ждём, пока пакетный файл отработает.
        WaitForSingleObject(execInfo.hProcess, INFINITE);
 
        //Проверяем, существует ли символическая ссылка C:\Test1\TestLink.
        //Теперь ссылка существует, поэтому функция вернёт true.
        Writeln(TFile.Exists('C:\Test1\TestLink', false));
 
        //Проверяем, существует ли символическая ссылка C:\Test1\TestLink
        //и файл C:\Test1\test2.txt, на которую она ссылается.
        //Ссылка C:\Test1\TestLink существует, но файл C:\Test1\test2.txt - нет,
        //поэтому функция вернёт false.
        Writeln(TFile.Exists('C:\Test1\TestLink', true));
 
        //Создаём файл C:\Test1\test2.txt.
        TFile.Create('C:\Test1\test2.txt').Free;
 
        //Опять проверяем, существует ли символическая ссылка C:\Test1\TestLink
        //и файл C:\Test1\test2.txt, на которую она ссылается.
        //Теперь ссылка C:\Test1\TestLink и файл C:\Test1\test2.txt существуют,
        //поэтому функция вернёт true.
        Writeln(TFile.Exists('C:\Test1\TestLink', true));
 
        //Удаляем символическую ссылку.
        TFile.Delete('C:\Test1\TestLink');
        //Удаляем директорию C:\Test1 и все файлы в ней.
        TDirectory.Delete('C:\Test1', true);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Получение цели из символической ссылки

Чуть выше мы упоминали работу с символической ссылкой, а теперь разберёмся, как узнать, на что ссылается символическая ссылка. Для этого у структуры TFile есть две функции с именем GetSymLinkTarget. Вот пример:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, ShellAPI, Windows;
 
var
    execInfo: TShellExecuteInfo;
    fileName: string;
    symLinkRec: TSymLinkRec;
 
begin
    try
        //Создаём временную директорию.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Создаём текстовый файл test.txt.
        TFile.WriteAllText('C:\Test1\test.txt', 'Здравствуй, мир!');
 
        //Создаём символическую ссылку test, которая будет ссылаться на файл test.txt.
        //Для создания символической ссылки нужно обладать правами администратора,
        //поэтому создавать её будем с помощью утилиты командной строки mklink,
        //которую будем вызывать от имени администратора.
        //Чтобы вызвать эту утилиту, придётся сначала создать пакетный файл,
        //а затем выполнить его.
        //Итак, сначала создаём пакетный файл с командой mklink.
        TFile.WriteAllText('C:\Test1\tmp.bat', 'mklink C:\Test1\test C:\Test1\test.txt');
        //Теперь выполняем пакетный файл от имени администратора.
        FillChar(execInfo, SizeOf(TShellExecuteInfo), 0);
        execInfo.cbSize := SizeOf(TShellExecuteInfo);
        execInfo.lpVerb := PWideChar('runas');
        execInfo.lpFile := PWideChar('C:\Test1\tmp.bat');
        execInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
        ShellExecuteEx(@execInfo);
        //Ждём, пока пакетный файл отработает.
        WaitForSingleObject(execInfo.hProcess, INFINITE);
 
        //Получаем имя файла, на который ссылается символическая ссылка.
        TFile.GetSymLinkTarget('C:\Test1\test', fileName);
        //Выводим, полученное имя файла. В результате увидим 'C:\Test1\test'.
        Writeln(fileName);
 
        //Получаем все характеристики символической ссылки.
        TFile.GetSymLinkTarget('C:\Test1\test', symLinkRec);
        //Выводим некоторые поля структуры symLinkRec.
        //Имя целевой папки или файла.
        Writeln(symLinkRec.TargetName);
        //Атрибуты целевого файла.
        Writeln(symLinkRec.Attr);
        //Размер целевого файла.
        Writeln(symLinkRec.Size);
        //Время и дата создания целевого файла или папки.
        Writeln(FormatDateTime('dd.mm.yyyy hh:nn:ss:', symLinkRec.TimeStamp));
 
        //Удаляем символическую ссылку.
        TFile.Delete('C:\Test1\test');
 
        //Удаляем директорию C:\Test1 и все файлы в ней.
        TDirectory.Delete('C:\Test1', true);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Чтение и изменение характеристик файла

В структуре TFile для чтения и изменения характеристик файла есть следующие методы:

        • GetAttributes – возвращает атрибуты файла, такие как «только чтение», «системный», «скрытый» и т.п.;
        • SetAttributes – устанавливает новый набор атрибутов для файла, такие как «только чтение», «системный», «скрытый» и т.п.;
        • GetCreationTime и GetCreationTimeUtc – возвращают дату и время создания файла;
        • SetCreationTime и SetCreationTimeUtc – устанавливают дату и время создания файла;
        • GetLastAccessTime и GetLastAccessTimeUtc – возвращают дату и время последнего обращения к файлу;
        • SetLastAccessTime и SetLastAccessTimeUtc – устанавливают дату и время последнего обращения к файлу;
        • GetLastWriteTime и GetLastWriteTimeUtc – возвращают дату и время последней записи в файл.
        • SetLastWriteTime и SetLastWriteTimeUtc – устанавливают дату и время последней записи в файл.

Функции, возвращающие и устанавливающие время, в конце имени которых есть суффикс «Utc», возвращают время в формате всемирного координированного времени (UTC).

Кроме приведённых здесь функций есть ещё недокументированные статические функции IntegerToFileAttributes и FileAttributesToInteger. Первая конвертирует атрибуты операционной системы для файла или директории в атрибуты, описанные в перечислении TFileAttribute, а вторая - обратно.

Рассмотрим примеры:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Rtti;
var
    fileAttribute: TFileAttribute;
 
begin
    try
        //Создаём директорию.
        TDirectory.CreateDirectory('C:\Test3');
        //Создаём пустые файлы для экспериментов.
        TFile.Create('C:\Test3\test1.txt').Free;
        TFile.Create('C:\Test3\test2.txt').Free;
 
        //Делаем файл скрытым, выставляя ему атрибут faHidden.
        TFile.SetAttributes('C:\Test3\test1.txt', [TFileAttribute.faHidden]);
        //Делаем файл доступным только для чтения, выставляя ему атрибут faReadOnly.
        TFile.SetAttributes('C:\Test3\test2.txt', [TFileAttribute.faReadOnly]);
        //Отображаем все установленные атрибуты файла test1.txt.
        //В результате отобразятся атрибут faHidden.
        for fileAttribute in TFile.GetAttributes('C:\Test3\test1.txt') do
            Writeln(TRttiEnumerationType.GetName<TFileAttribute>(fileAttribute));
        //Отображаем все установленные атрибуты файла test2.txt.
        //В результате отобразится атрибут faReadOnly.
        for fileAttribute in TFile.GetAttributes('C:\Test3\test2.txt') do
            Writeln(TRttiEnumerationType.GetName<TFileAttribute>(fileAttribute));
 
        //Выводим дату и время создания файла test1.txt.
        //В результате отобразится дата и время на момент создания файла.
        Writeln(DateTimeToStr(TFile.GetCreationTime('C:\Test3\test1.txt')));
        //Устанавливаем дату и время создания файла.
        TFile.SetCreationTime('C:\Test3\test1.txt', StrToDateTime('01.02.03 11:12:13'));
        //Выводим дату и время создания файла.
        //В результате отобразится 01.02.2003 11:12:13.
        Writeln(DateTimeToStr(TFile.GetCreationTime('C:\Test3\test1.txt')));
        //Выводим дату и время создания файла в формате UTC, т.е. без учёта часового пояса.
        //В результате отобразится 01.02.2003 8:12:13, т.е. -3 часа по Москве.
        Writeln(DateTimeToStr(TFile.GetCreationTimeUtc('C:\Test3\test1.txt')));
 
        //Выводим дату и время последнего обращения к файлу.
        Writeln(DateTimeToStr(TFile.GetLastAccessTime('C:\Test3\test1.txt')));
        //Устанавливаем дату и время последнего обращения к файлу.
        TFile.SetLastAccessTime('C:\Test3\test1.txt', StrToDateTime('01.02.03 11:12:14'));
        //Выводим дату и время последнего обращения к файлу.
        //В результате отобразится 01.02.2003 11:12:14.
        Writeln(DateTimeToStr(TFile.GetLastAccessTime('C:\Test3\test1.txt')));
 
        //Выводим дату и время последней записи в файл.
        Writeln(DateTimeToStr(TFile.GetLastWriteTime('C:\Test3\test1.txt')));
        //Устанавливаем дату и время последней записи в файл.
        TFile.SetLastWriteTime('C:\Test3\test1.txt', StrToDateTime('01.02.03 11:12:15'));
        //Выводим дату и время последней записи в файл.
        //В результате отобразится 01.02.2003 11:12:15.
        Writeln(DateTimeToStr(TFile.GetLastWriteTime('C:\Test3\test1.txt')));
 
        //Удаляем директорию и все вложенные файлы.
        TDirectory.Delete('C:\Test3', true);
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Копирование, перемещение и переименование файлов

Для копирования файла у структуры TFile есть метод Copy, а для перемещения или переименования – метод Move.

Метод Copy кидает ошибку, если файл с таким же именем, как файл назначения существует. Однако вы можете установить третий параметр метода Overwrite в true, и тогда операция копирования всё равно выполнится.

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

Метод Move кидает ошибку, если файл назначения существует.

Вот пример использования методов Copy и Move:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Создаём директории.
        TDirectory.CreateDirectory('C:\Test1');
        TDirectory.CreateDirectory('C:\Test2');
 
        //Создаём файл.
        TFile.Create('C:\Test1\file1.txt').Free;
 
        //Копируем файл в другую директорию.
        TFile.Copy('C:\Test1\file1.txt', 'C:\Test2\file1.txt');
 
        //Ещё раз пытаемся скопировать файл, вместо уже существующего.
        //При этом мы получим ошибку EInOutError с текстом 'The specified file already exists'.
        try
            TFile.Copy('C:\Test1\file1.txt', 'C:\Test2\file1.txt');
        except
            //Отлавливаем ошибку EInOutError и ничего не делаем.
            on EInOutError do;
        end;
 
        //Опять копируем файл вместо существующего,
        //но теперь выставляем параметр Overwrite в true.
        //В этом случае существующий файл заменится на новый.
        TFile.Copy('C:\Test1\file1.txt', 'C:\Test2\file1.txt', true);
 
        //Переименовываем файл, оставляя его в той же директории.
        TFile.Move('C:\Test1\file1.txt', 'C:\Test1\file2.txt');
 
        //Переносим файл в другую директорию.
        TFile.Move('C:\Test1\file2.txt', 'C:\Test2\file2.txt');
 
        //Переносим файл в другую директорию и одновременно переименовываем его.
        TFile.Move('C:\Test2\file2.txt', 'C:\Test1\file3.txt');
 
        //Удаляем директории и все вложенные файлы.
        TDirectory.Delete('C:\Test1', true);
        TDirectory.Delete('C:\Test2', true);
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Шифрование и расшифровывание файлов

Шифрование и расшифровывание файла можно сделать с помощью, соответственно, методов Encrypt и Decrypt. После шифрования вы сможете работать с файлом как и раньше. Всю работу по чтению из зашифрованного файла, запись в него и т.д. берёт на себя операционная система. Вот пример использования функций.

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Создаём директорию.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Создаём файл.
        TFile.WriteAllText('C:\Test1\file1.txt', 'Содержимое файла');
 
        //Шифруем файл.
        TFile.Encrypt('C:\Test1\file1.txt');
 
        //Расшифровываем файл.
        TFile.Decrypt('C:\Test1\file1.txt');
 
        //Удаляем директории и все вложенные файлы.
        TDirectory.Delete('C:\Test1', true);
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Замена содержимого файла

У структуры TFile есть метод Replace, позволяющий заменить содержимое файла на содержимое другого файла. По сути, происходит замена одного файла на другой, но при замене сохранятся все атрибуты файла, содержимого которого мы меняем. Атрибуты копируются следующие: время создания, краткое название файла, идентификатор объекта, дискреционный список контроля доступа (DACL), атрибуты безопасности, шифрование, сжатие и именованные потоки (не в заменяемом файле). Однако вы можете сказать функции Replace, что сохранять атрибуты не нужно, в этом случае вы можете установить четвёртый параметр функции IgnoreMetadataErrors в true. Также для заменяемого файла метод Replace создаёт резервную копию.

Вот примеры использования функции Replace:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Создаём директории.
        TDirectory.CreateDirectory('C:\Test1');
 
        //Создаём два файла.
        TFile.WriteAllText('C:\Test1\file1.txt', 'Содержимое первого файла');
        TFile.WriteAllText('C:\Test1\file2.txt', 'Содержимое второго файла');
 
        //Шифруем только второй файл file2.txt.
        TFile.Encrypt('C:\Test1\file2.txt');
 
        //Заменяем содержимое файла file2.txt на содержимое файла file1.txt.
        //При этом в файл backup.txt отправляется старое содержимое файла file2.txt.
        TFile.Replace('C:\Test1\file1.txt', 'C:\Test1\file2.txt', 'C:\Test1\backup.txt');
 
        //После замены содержимого второй файл останется зашифрованным.
        //В консоли появится надпись 'Файл file2.txt зашифрован.'.
        if TFileAttribute.faEncrypted in TFile.GetAttributes('C:\Test1\file2.txt') then
            Writeln('Файл file2.txt зашифрован.');
 
        //Удаляем директории и все вложенные файлы.
        TDirectory.Delete('C:\Test1', true);
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Использование TPath

Структура TPath используется в Delphi для работы с путями. Она содержит только статические методы и свойства. Давайте рассмотрим их.

Специальные символы

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

        • DirectorySeparatorChar – символ для разделения директорий разного уровня;
        • AltDirectorySeparatorChar – альтернативный символ для разделения директорий разного уровня;
        • ExtensionSeparatorChar – символ для разделения имени от расширения в имени файла;
        • PathSeparator – символ для разделения путей в переменных окружения;
        • VolumeSeparatorChar – символ для отделения буквы диска от остального пути.

Вот пример, с выводом значений всех свойств TPath:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Результат будет '\'.
        Writeln(TPath.DirectorySeparatorChar);
        //Результат будет '/'.
        Writeln(TPath.AltDirectorySeparatorChar);
        //Результат будет '.'.
        Writeln(TPath.ExtensionSeparatorChar);
        //Результат будет ';'.
        Writeln(TPath.PathSeparator);
        //Результат будет ':'.
        Writeln(TPath.VolumeSeparatorChar);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Получение путей к специальным и пользовательским директориям

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

        • GetAlarmsPath – путь к директории для хранения пользовательских звуков для будильника. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. В Windows и OS X эта функция вернёт то же, что и функция GetMusicPath.
        • GetCachePath – путь к директории, в которой ваше приложение может сохранять файлы кеша.
        • GetCameraPath – путь к пользовательской директории, в которую сохраняются фотографии, сделанные с помощью камеры устройства. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. В Windows и OS X эта функция вернёт то же, что и функция GetPicturesPath.
        • GetDocumentsPath – путь к директории для хранения документов пользователя.
        • GetDownloadsPath – путь к директории для хранения скачанных пользователем файлов. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetHomePath – возвращает либо домашний путь пользователя (в Linux - /home/<username>), либо путь к временной папке приложения (В Windows Vista и позже - C:\Users\<username>\AppData\Roaming), либо путь к хранилищу (в Android - /data/data/<application ID>/files).
        • GetLibraryPath – путь к директории для хранения данных вашего приложения. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку. Например, для Windows - C:\Program Files\<application folder>, для Android - /data/app-lib/<application ID>.
        • GetMoviesPath – путь к директории для хранения видео пользователя. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetMusicPath – путь к директории для хранения музыки пользователя. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetPublicPath – путь к директории, где можно сохранять данные приложения, доступные другим приложениям. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. Например, Windows Vista и позже - C:\ProgramData, OS X - /Users/<username>/Public.
        • GetPicturesPath – путь к директории для хранения фотографий и картинок пользователя. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetRingtonesPath – путь к директории для хранения пользовательских звуков для звонка. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. В Windows и OS X эта функция вернёт то же, что и функция GetMusicPath.
        • GetSharedAlarmsPath – путь к директории для хранения общих звуков для будильника. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. В Windows и OS X эта функция вернёт то же, что и функция GetSharedMusicPath.
        • GetSharedCameraPath – путь к общей директории, в которую сохраняются фотографии, сделанные с помощью камеры устройства. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. В Windows и OS X эта функция вернёт то же, что и функция GetSharedPicturesPath.
        • GetSharedDocumentsPath – путь к общей директории для хранения документов пользователя. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetSharedDownloadsPath – путь к общей директории для хранения скачанных файлов. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetSharedMoviesPath – путь к общей директории для хранения видео. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetSharedMusicPath – путь к общей папки для хранения музыки. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetSharedPicturesPath – путь к общей директории для хранения фотографий и картинок. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS.
        • GetSharedRingtonesPath – путь к общей папке для хранения звуков для звонка. Если операционная система не поддерживает такую директорию, то эта функция вернёт пустую строку, например, iOS. В Windows и OS X эта функция вернёт то же, что и функция GetSharedMusicPath.
        • GetTempPath – путь к папке для хранения временных файлов. Файлы, сохранённые здесь, могут быть удалены после перезагрузки системы или между сессиями приложения.

Вот пример использования функций:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Результат будет: C:\Users\username\Music
        Writeln(TPath.GetAlarmsPath);
        //Результат будет: C:\Users\username\AppData\Local
        Writeln(TPath.GetCachePath);
        //Результат будет: C:\Users\username\Pictures
        Writeln(TPath.GetCameraPath);
        //Результат будет: C:\Users\username\Documents
        Writeln(TPath.GetDocumentsPath);
        //Результат будет: C:\Users\username\AppData\Local
        Writeln(TPath.GetDownloadsPath);
        //Результат будет: C:\Users\username\AppData\Roaming
        Writeln(TPath.GetHomePath);
        //Результат будет: C:\Projects\Delphi\Tokyo\IOUtilsTest\Win32\Debug\
        Writeln(TPath.GetLibraryPath);
        //Результат будет: C:\Users\username\Videos
        Writeln(TPath.GetMoviesPath);
        //Результат будет: C:\Users\username\Music
        Writeln(TPath.GetMusicPath);
        //Результат будет: C:\ProgramData
        Writeln(TPath.GetPublicPath);
        //Результат будет: C:\Users\username\Pictures
        Writeln(TPath.GetPicturesPath);
        //Результат будет: C:\Users\username\Music
        Writeln(TPath.GetRingtonesPath);
        //Результат будет: C:\Users\Public\Music
        Writeln(TPath.GetSharedAlarmsPath);
        //Результат будет: C:\Users\Public\Pictures
        Writeln(TPath.GetSharedCameraPath);
        //Результат будет: C:\Users\Public\Documents
        Writeln(TPath.GetSharedDocumentsPath);
        //Результат будет: C:\ProgramData
        Writeln(TPath.GetSharedDownloadsPath);
        //Результат будет: C:\Users\Public\Videos
        Writeln(TPath.GetSharedMoviesPath);
        //Результат будет: C:\Users\Public\Music
        Writeln(TPath.GetSharedMusicPath);
        //Результат будет: C:\Users\Public\Pictures
        Writeln(TPath.GetSharedPicturesPath);
        //Результат будет: C:\Users\Public\Music
        Writeln(TPath.GetSharedRingtonesPath);
        //Результат будет: c:\temp\
        Writeln(TPath.GetTempPath);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Работа с путями

У структуры TPath есть много методов для работы с путями, например, для соединения путей или для разбивки:

        • ChangeExtension – изменяет расширение файла в указанном пути. Функция не меняет имя реального файла, она только возвращает новую получившуюся строку.
        • Combine – соединяет два пути в один. Например, если в первом параметре указан абсолютный путь к директории (например, C:\Test1), а во втором – имя файла (например, test.txt), то в результате функция вернёт абсолютный путь к файлу (получим C:\Test1\test.txt). Если во втором параметре указан абсолютный путь, то функция просто вернёт его, игнорируя первый параметр.
        • GetDirectoryName – извлекает путь к директории из пути к файлу. Например, для пути «C:\MyApp\Temp\temp.txt» функция вернёт «C:\MyApp\Temp». Функция вернёт пустую строку, если в пути к файлу нет части с диском и директорией, например, если вы передадите в функцию строку «test.txt».
        • GetExtendedPrefix – возвращает расширенный тип префикса для указанного пути, если он есть. Возможные варианты \\?\ или \\?\UNC\.
        • GetExtension – извлекает расширение файла из пути. Результат содержит точку в начале строки. Если у имени файла нет расширения, то функция вернёт пустую строку.
        • GetFileName – извлекает имя файла с расширением из пути к файлу. Например, для пути «C:\Test1\test.txt» функция вернёт «test.txt».
        • GetFileNameWithoutExtension – извлекает имя файла без расширения из пути к файлу. Например, для пути «C:\Test1\test.txt» функция вернёт «test».
        • GetFullPath – возвращает абсолютный путь для указанного относительного пути. При создании абсолютного пути функция использует текущую директорию. Например, если текущая директория «C:\MyApp», то для пути «\Temp\test.txt», функция вернёт «C:\MyApp\Temp\test.txt». Если вы передали в функцию абсолютный путь, то функция вернёт его без изменений.
        • GetPathRoot – возвращает корень для указанного пути. Например, для пути «C:\MyApp\Temp», функция вернёт «C:\».
        • HasExtension – функция проверяет, есть ли у указанного имени файла расширение.
        • HasValidFileNameChars – функция проверяет, содержит ли имя файла или шаблон имени файла только разрешённые символы.
        • HasValidPathChars – функция проверяет, содержит ли путь только разрешённые символы.
        • IsDriveRooted – функция проверяет, является ли путь абсолютным и содержит ли букву логического диска.
        • IsExtendedPrefixed – функция проверяет, содержит ли путь расширенный префикс.
        • IsPathRooted – проверяет, является ли путь абсолютным.
        • IsRelativePath – проверяет, является ли путь относительным.
        • IsUNCPath – проверяет, указан ли путь в UNC (Universal Naming Convention) формате. Путь в формате UNC начинается с двух слешей, например, «\\computer\folder».
        • IsUNCRooted – проверяет, указан ли корень в пути в формате UNC.
        • MatchesPattern – проверяет соответствие имени файла шаблону.

Вот примеры использования функций для работы с путями:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils, Rtti;
 
begin
    try
        //Меняем расширение файла. Результат будет 'C:\MyApp\Temp\temp.dat'.
        Writeln(TPath.ChangeExtension('C:\MyApp\Temp\temp.txt', '.dat'));
 
        //Соединяем два пути. Результат будет 'C:\MyApp\Temp\temp.txt'.
        Writeln(TPath.Combine('C:\MyApp\', 'Temp\temp.txt'));
 
        //Извлекаем путь к директории. Результат будет 'C:\MyApp\Temp'.
        Writeln(TPath.GetDirectoryName('C:\MyApp\Temp\temp.txt'));
 
        //Получаем тип расширенного префикса.
        //Результат будет pptNoPrefix.
        Writeln(TRttiEnumerationType.GetName<TPathPrefixType>(
                TPath.GetExtendedPrefix('C:\MyApp\Temp\temp.txt')));
        //Результат будет pptExtended.
        Writeln(TRttiEnumerationType.GetName<TPathPrefixType>(
                TPath.GetExtendedPrefix('\\?\C:\MyApp\Temp\temp.txt')));
        //Результат будет pptExtendedUNC.
        Writeln(TRttiEnumerationType.GetName<TPathPrefixType>(
                TPath.GetExtendedPrefix('\\?\UNC\my_computer\shared_folder')));
 
        //Извлекаем расширение файла. Результат будет '.txt'.
        Writeln(TPath.GetExtension('C:\MyApp\Temp\temp.txt'));
 
        //Извлекаем имя файла с расширением. Результат будет 'temp.txt'.
        Writeln(TPath.GetFileName('C:\MyApp\Temp\temp.txt'));
 
        //Извлекаем имя файла без расширения. Результат будет 'temp'.
        Writeln(TPath.GetFileNameWithoutExtension('C:\MyApp\Temp\temp.txt'));
 
        //Получаем абсолютный путь из относительного. Результат будет 'C:\MyApp\Temp\temp.txt'.
        Writeln(TPath.GetFullPath('\MyApp\Temp\temp.txt'));
 
        //Получаем корень для указанного пути. Результат будет 'C:\'.
        Writeln(TPath.GetPathRoot('C:\MyApp\Temp\temp.txt'));
 
        //Проверяем, есть ли у имени файла расширение. Результат будет TRUE.
        Writeln(TPath.HasExtension('C:\MyApp\Temp\temp.txt'));
 
        //Проверяем, все ли символы в имени файла разрешены.
        //Результат будет TRUE.
        Writeln(TPath.HasValidFileNameChars('temp.txt', false));
        //Результат будет FALSE.
        Writeln(TPath.HasValidFileNameChars('t?emp*.txt', false));
        //Проверяем, все ли символы в шаблоне имени файла разрешены. Результат будет TRUE.
        Writeln(TPath.HasValidFileNameChars('t?emp*.txt', true));
 
        //Проверяем, все ли символы в пути разрешены.
        //Результат будет TRUE.
        Writeln(TPath.HasValidPathChars('C:\MyApp\Temp\temp.txt', false));
        //Результат будет FALSE.
        Writeln(TPath.HasValidPathChars('C:\MyApp\<Temp>\temp.txt', false));
 
        //Проверяем, является ли путь абсолютным и начинается ли он с имени диска.
        //Результат будет TRUE.
        Writeln(TPath.IsDriveRooted('C:\MyApp\Temp\temp.txt'));
        //Результат будет FALSE.
        Writeln(TPath.IsDriveRooted('\MyApp\Temp\temp.txt'));
        //Результат будет FALSE.
        Writeln(TPath.IsDriveRooted('\\my_computer\MyApp\Temp\temp.txt'));
 
        //Проверяем, содержит ли путь расширенный префикс.
        //Результат будет FALSE.
        Writeln(TPath.IsExtendedPrefixed('C:\MyApp\Temp\temp.txt'));
        //Результат будет TRUE.
        Writeln(TPath.IsExtendedPrefixed('\\?\C:\MyApp\Temp\temp.txt'));
 
        //Проверяем, является ли путь абсолютным.
        //Результат будет TRUE.
        Writeln(TPath.IsPathRooted('C:\MyApp\Temp\temp.txt'));
        //Результат будет TRUE.
        Writeln(TPath.IsPathRooted('\MyApp\Temp\temp.txt'));
        //Результат будет FALSE.
        Writeln(TPath.IsPathRooted('..\MyApp\Temp\temp.txt'));
        //Результат будет TRUE.
        Writeln(TPath.IsPathRooted('\\my_computer\MyApp\Temp\temp.txt'));
 
        //Проверяем, является ли путь относительным.
        //Результат будет FALSE.
        Writeln(TPath.IsRelativePath('C:\MyApp\Temp\temp.txt'));
        //Результат будет FALSE.
        Writeln(TPath.IsRelativePath('\MyApp\Temp\temp.txt'));
        //Результат будет TRUE.
        Writeln(TPath.IsRelativePath('..\MyApp\Temp\temp.txt'));
        //Результат будет FALSE.
        Writeln(TPath.IsRelativePath('\\my_computer\MyApp\Temp\temp.txt'));
 
        //Проверяем, указан ли путь в UNC формате.
        //Результат будет TRUE.
        Writeln(TPath.IsUNCPath('\\?\UNC\my_computer\shared_folder'));
 
        //Проверяем, указан ли корень в пути в формате UNC.
        //Результат будет TRUE.
        Writeln(TPath.IsUNCRooted('\\?\UNC\my_computer\shared_folder'));
 
        //Проверяем соответствие имени файла шаблону.
        //Результат будет TRUE.
        Writeln(TPath.MatchesPattern('Temp.txt', '*.txt', false));
        //Результат будет TRUE.
        Writeln(TPath.MatchesPattern('Temp.txt', 't???.txt', false));
        //Результат будет FALSE.
        Writeln(TPath.MatchesPattern('Temp.txt', '*.dat', false));
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Функции для создания временных файлов

Часто в программе нужно создавать временные файлы, для которых нужно придумывать уникальные имена. Чтобы не придумывать свой собственный алгоритм для формирования уникального имени файла вы можете использовать следующие функции структуры TPath: GetTempFileName, GetGUIDFileName или GetRandomFileName. Первая функция создаёт пустой временный файл в папке операционной системы для хранения временных файлов, (см. функцию TPath.GetTempPath) и возвращает абсолютное имя созданного файла. Остальные две функции только генерируют имя файла и не гарантируют его уникальность.

Вот примеры использования функций:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
var
    fileName: string;
 
begin
    try
        //Создаём пустой временный файл в папке для временных файлов операционной системы.
        fileName := TPath.GetTempFileName;
        //Имя файла всё время будет разным, например, 'c:\temp\tmp74D0.tmp'.
        Writeln(fileName);
        //Удаляем созданный временный файл.
        TFile.Delete(fileName);
 
        //Создаём GUID, который можно использовать в качестве имени файла.
        fileName := TPath.GetGUIDFileName(false);
        //Результат всё время будет разный, например, 'F45F5BC9F72A454D8DCF205206A0E0C2'.
        Writeln(fileName);
        //Чтобы получить из GUID настоящее имя для файла, добавляем путь и расширение.
        fileName := TPath.Combine(TPath.GetTempPath, fileName + '.txt');
        //Теперь результат будет 'c:\temp\62AD3AB101964F7BBB0216694840F8C4.txt'.
        Writeln(fileName);
 
        //Создаём имя для временного файла.
        fileName := TPath.GetRandomFileName;
        //Результат всё время будет разный, например, 'eJA6Q5HG.0Qs'.
        Writeln(fileName);
        //Добавляем путь.
        fileName := TPath.Combine(TPath.GetTempPath, fileName);
        //Теперь результат будет 'c:\temp\eJA6Q5HG.0Qs'.
        Writeln(fileName);
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Проверка наличия диска

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

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
begin
    try
        //Проверяем, есть ли на компьютере диск, указанный в пути, т.е. диск C:.
        //Результат будет TRUE.
        Writeln(TPath.DriveExists('C:\Temp1'));
        //Результат будет TRUE.
        Writeln(TPath.DriveExists('C:'));
        //Результат будет FALSE.
        Writeln(TPath.DriveExists('Z:\Temp1'));
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Функции проверки символов для использования в пути и имени файла

Кроме всего вышеперечисленного у структуры TPath есть функции IsValidPathChar и IsValidFileNameChar для проверки символов, подходят ли они для использования в пути и в имени файла и функции GetInvalidFileNameChars и GetInvalidPathChars, которые возвращают символы, которые не допускается использовать в имени файла и в пути. Имея эти символы, вы самостоятельно сможете создать функции, которые будут проверять имена файлов и пути. Посмотрим, что возвращают эти функции:

program Project1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
    SysUtils, IOUtils;
 
var
    c: char;
 
begin
    try
        //Проверяем, можно ли использовать символы в пути.
        //Результат будет TRUE.
        Writeln(TPath.IsValidPathChar('a'));
        //Результат будет TRUE.
        Writeln(TPath.IsValidPathChar('\'));
        //Результат будет FALSE.
        Writeln(TPath.IsValidPathChar('<'));
 
        //Проверяем, можно ли использовать символы в имени файла.
        //Результат будет TRUE.
        Writeln(TPath.IsValidFileNameChar('a'));
        //Результат будет FALSE.
        Writeln(TPath.IsValidFileNameChar('\'));
        //Результат будет FALSE.
        Writeln(TPath.IsValidFileNameChar('<'));
 
        //Выдаём символы, которые нельзя использовать в имени файла.
        //В результате будет примерно так (не все символы могут быть отображены в консоли):
        //☺☻♥♦♣♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼"*/:<>?\|
        for c in TPath.GetInvalidFileNameChars do
            Write(c);
        Writeln;
        //Выдаём коды символов, которые нельзя использовать в имени файла.
        //В результате будет:
        //0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,34,42,47,58,60,62,63,92,124,
        for c in TPath.GetInvalidFileNameChars do
        begin
            Write(integer(c));
            Write(',');
        end;
        Writeln;
 
        //Выдаём символы, которые нельзя использовать в пути.
        //В результате будет примерно так (не все символы могут быть отображены в консоли):
        //☺☻♥♦♣♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼"<>|
        for c in TPath.GetInvalidPathChars do
            Write(c);
        Writeln;
        //Выдаём коды символов, которые нельзя использовать в пути.
        //В результате будет:
        //0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,34,60,62,124,
        for c in TPath.GetInvalidPathChars do
        begin
            Write(integer(c));
            Write(',');
        end;
        Writeln;
 
        Readln;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Получение атрибутов файлов и директорий

И в завершении вкратце упомяну ещё методы GetAttributes и SetAttributes у структуры TPath. Они умеют читать и устанавливать атрибуты файлов и директорий. Описывать их нет смысла, т.к. они по своим функциям повторяют одноимённые методы структур TFile и TDirectory.

Заключение

Как видите, набор инструментов в юните System.IOUtils очень большой. Поверьте, при работе с файлами он существенно облегчает работу. Надеюсь, что статья понравится не только тем, кто ещё не был знаком с замечательным юнитом System.IOUtils, но и тем, кто уже его использует. Ведь и в том, что, казалось бы, уже хорошо знакомо, часто можно найти что-то новое и неизученное.

Tags: IOUtils Учебники по программированию Delphi

Комментарии   

Владислав Шевяков
+3 #1 Владислав Шевяков 10.02.2018 09:56
Статья хорошая. Не хватает главного, а именно, ответа на вопрос: ЗАЧЕМ в Embarcadero был добавлен модуль System.IOUtils?
На самом деле всё просто, IOUtils адаптирован под все платформы поддерживаемые Embarcadero на данный момент (Windows, Android, iOS, OSx). Т.е. использование описанных выше классов, в любой операционке приведет к корректному выполнению операций файлового ввода - вывода. Что согласитесь, задача весьма не тривиальная.
Цитировать
ЧурепУшка
0 #2 ЧурепУшка 24.03.2018 13:26
Решил попробовать запихивать директории в ListView, по критерию поиска указанному в searchbox1.text
Но
Цитата:

var
s:string;
begin
for s in TDirectory.GetFileSystemEntries('D:\Тест\SADD\Archive','*'+ SearchBox1.Text+'*') do
begin ListView1.AddItem(TPath.GetFullPath(s), Sender); end;
end;
Почему-то не выдаёт результатов если папка называется "Новая (1)" а в seachbox-e написано "новая", то есть присутствует чувствительность к регистру букв (латинских это не касается).
Цитировать
Рустам
-1 #3 Рустам 30.08.2018 18:06
Функций очень много полезных. Но не нашел такие:
1. Узнать размер тома в Мб
2. Подсчитать количество файлов в директории
Цитировать
frkbvfnjh
+3 #4 frkbvfnjh 05.02.2020 16:23
Статья просто ахрененная! Открыл для себя новый мир! Нафига я сам эти функции писал. Теперь думаю проштудировать весь состав модулей Delphi и их функций. В новых версиях Delphi оказывается программировать одно удовольствие, даже и писать то код почти не надо - все уже готово!
Цитировать
DarkMaster
+2 #5 DarkMaster 20.07.2020 13:00
Цитирую frkbvfnjh:
Нафига я сам эти функции писал.
.... даже и писать то код почти не надо - все уже готово!

Если бы тысячи программеров не писали эти свои велосипеды - и IOUtils бы никогда не появилось ;-)
Цитировать

Добавить комментарий