Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.07.13;
Скачать: [xml.tar.bz2];

Вниз

очистка каталога   Найти похожие ветки 

 
Yury   (2008-06-12 10:18) [0]

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


 
savyhinst ©   (2008-06-12 10:22) [1]

var
 sr:TSearchRec;
begin
 if findFirst("katalog\*.*",faAnyFile,sr)=0 then
 repeat
   if (sr.name<>".")and(sr.name<>"..") then
     DeleteFile(PChar("katalog\"+sr.name);
 until FindNext(sr)<>0;
end;


 
Yury   (2008-06-12 10:23) [2]

а встроенной функции типа deleteFile нет?


 
savyhinst ©   (2008-06-12 10:28) [3]

ХЗ, вроде бы нету


 
Anatoly Podgoretsky ©   (2008-06-12 10:36) [4]

> Yury  (12.06.2008 10:18:00)  [0]

Смотри справку по ShFileOperation


 
Loginov Dmitry ©   (2008-06-12 10:37) [5]

> [1] savyhinst ©   (12.06.08 10:22)


1) А поиск закрывать ныне не модно?
2) Зачем PChar? Это лишнее копирование строки.
3) DeleteFile попытается удалить не только файлы.
4) А не нарушит ли удаление файла в цикле логику findFirst/FindNext? (я это не проверял, посколько всегда удаляю с использованием временного TStringList"a)

> а встроенной функции типа deleteFile нет?


В RxLib"е есть. Бери.


 
ZENsan ©   (2008-06-12 11:25) [6]


> 4) А не нарушит ли удаление файла в цикле логику findFirst/FindNext?
>  (я это не проверял, посколько всегда удаляю с использованием
> временного TStringList"a)


Не нарушит. Временный стринглист - это тоже лишнее.

Можно очистить ещё и так (если без ShFileOperation):

procedure TUtils.EmptyFolder(const Path: String; Level: Integer = 0);
var
 Dir: TSearchRec;
begin
 if Level > 1 then
   Exit;
 if not DirectoryExists(Path) then
   Exit;
 try
   ChDir(Path);
   if FindFirst("*.*", $3F, Dir) = 0 then
     repeat
       if (Dir.Name = ".") or (Dir.Name = "..") then
         Continue;
       if Dir.Attr and faDirectory = 0 then
         DeleteFile(Dir.Name)
       else
         begin
           EmptyFolder(ExcludeTrailingPathDelimiter(Path) + "\"  +
             Dir.Name + "\", Level + 1);
           RemoveDir(Dir.Name);
         end;
     until FindNext(Dir) <> 0;
 finally
   ChDir(ExtractFilePath(ParamStr(0)));
 end;
end;


 
ZENsan ©   (2008-06-12 11:27) [7]

ну и FindClose.. как бы тоже дописать для моды :)


 
Amoeba ©   (2008-06-12 12:46) [8]

И зачем так сложно? Проще использовать ShFileOperation:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=91


 
Anatoly Podgoretsky ©   (2008-06-12 13:19) [9]


> ну и FindClose.. как бы тоже дописать для моды :)

Кому мода, а кому нормальное написание программ. Модники обычно долго не живут.


 
ZENsan ©   (2008-06-12 18:55) [10]

Вообще-то если внимательно читать, уважаемый, я подколол Логинова Дмитрия... я про моду ничего не говорю.


 
ZENsan ©   (2008-06-12 18:58) [11]

>>И зачем так сложно? Проще использовать ShFileOperation:
Она не всегда Thread-safe. Конечно легче ShFileOperation.


procedure TUtils.EmptyFolder(const Path: String; Level: Integer = 0);
var
 Dir: TSearchRec;
begin
 if Level > 1 then
   Exit;
 if not DirectoryExists(Path) then
   Exit;
 try
   ChDir(Path);
   if FindFirst("*.*", $3F, Dir) = 0 then
     try
       repeat
         if (Dir.Name = ".") or (Dir.Name = "..") then
           Continue;
         if Dir.Attr and faDirectory = 0 then
           DeleteFile(Dir.Name)
         else
           begin
             EmptyFolder(ExcludeTrailingPathDelimiter(Path) + "\"  +
               Dir.Name + "\", Level + 1);
             RemoveDir(Dir.Name);
           end;
       until FindNext(Dir) <> 0;
     finally
       FindClose(Dir);
     end;
 finally
   ChDir(ExtractFilePath(ParamStr(0)));
 end;
end;


 
Loginov Dmitry.   (2008-06-12 19:48) [12]


> Она не всегда Thread-safe



> ChDir(Path);



> ChDir(ExtractFilePath(ParamStr(0)));


Хм... Наряду с этим примером странно слышать про Thread-safe...


 
Amoeba ©   (2008-06-12 20:25) [13]


> ZENsan ©   (12.06.08 18:58) [11]
>
> >>И зачем так сложно? Проще использовать ShFileOperation:
>
> Она не всегда Thread-safe.

Как правило, это не актуально.


 
ZENsan ©   (2008-06-13 15:46) [14]


> Хм... Наряду с этим примером странно слышать про Thread-
> safe...

А ты телепат, и знаешь все тонкости задачи. Это пример человеку, который спрашивал. Вам не годится - не юзайте. А кому надо изменит, что надо и пойдёт.


 
ZENsan ©   (2008-06-13 16:24) [15]

Я с головы пишу, поэтому приношу извинения что мой код далеко не идеальный и вы находите в нём недочёты. Логинов Дмитрий.
Именно поэтому я налету писал ChDir чтобы не думать там с этими слешами и ExcludeTrailingPathDelimiter...


 
Riply ©   (2008-06-13 17:24) [16]

Написала для себя небольшую процедуру удаления директории.
Да вот все руки не доходят погонять и потестировать ее по полной программе,
дабы пометить как готовую к употреблению и забыть :)
Чем черт не шутит, может и найдутся желающие выполнить за лентяку ее работу :)
Предупреждаю сразу о паре скользких моментов:
нет проверки на FILE_ATTRIBUTE_REPARSE_POINT и довольно шаткая проверка на ".", "..".

Если все будет удачно, то в ней заложен большой потенциал для оптимизации
(я запрашивала только по одному объекту при сканировании и,
соответственно, не пыталась управлять порядком удаления, что не есть кузяво :)

Первая часть:

function Nt_RemoveDirRecursivelyU(const pPathForDelete: PUNICODE_STRING; DeleteSelf: Boolean): NTSTATUS;

implementation

const
QUERY_FILE_FS_INC               = $1000;

procedure Us_InitLen_(const pUs: PUNICODE_STRING; const pwSour: PWideChar; const BytesInSource: LongWord);
begin
with pUs^ do
 begin
  Buffer := pwSour;
  Length := BytesInSource;
  MaximumLength := BytesInSource;
 end;
end;

function Nt_SetObjDisposInfoDelete(const FSObjHandle: THandle): NTSTATUS;
var
FileDispInfo: FILE_DISPOSITION_INFORMATION;
IoBlock: IO_STATUS_BLOCK;
begin
FileDispInfo.DeleteFile := True;
Result := NtSetInformationFile(FSObjHandle, @IoBlock, @FileDispInfo,
                               SizeOf(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
end;

function _Nt_SetObjAttributes(const FSObjHandle: THandle; const cbAttr: DWord): NTSTATUS;
var
FileBaseInfo: FILE_BASIC_INFORMATION;
IoBlock: IO_STATUS_BLOCK;
begin
FillChar(FileBaseInfo, SizeOf(FILE_BASIC_INFORMATION), 0);
FileBaseInfo.FileAttributes := cbAttr;
Result := NtSetInformationFile(FSObjHandle, @IoBlock, @FileBaseInfo,
                               SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
end;

function Nt_DeleteObjectFS(const FSObjHandle: THandle; const FileAttr: DWord): NTSTATUS;
var
FileBaseInfo: FILE_BASIC_INFORMATION;
FileDispInfo: FILE_DISPOSITION_INFORMATION;
IoBlock: IO_STATUS_BLOCK;
begin
FileDispInfo.DeleteFile := True;
if (FileAttr and (FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_SYSTEM)) <> 0 then
 begin
  FillChar(FileBaseInfo, SizeOf(FILE_BASIC_INFORMATION), 0);
  FileBaseInfo.FileAttributes := FILE_ATTRIBUTE_NORMAL;
  Result := NtSetInformationFile(FSObjHandle, @IoBlock, @FileBaseInfo,
                                 SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
  if Result = STATUS_SUCCESS
   then Result := NtSetInformationFile(FSObjHandle, @IoBlock, @FileDispInfo,
                                       SizeOf(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
 end
else Result := NtSetInformationFile(FSObjHandle, @IoBlock, @FileDispInfo,
                                    SizeOf(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
end;

function Nt_DeleteObject(const pObjAttr: POBJECT_ATTRIBUTES; const FileAttr: DWord): NTSTATUS;
var
IoBlock: IO_STATUS_BLOCK;
FileHandle: THandle;
begin
if (FileAttr and FILE_ATTRIBUTE_DIRECTORY) = 0
 then Result := NtCreateFile(@FileHandle, _DELETE or FILE_WRITE_ATTRIBUTES, pObjAttr, @IoBlock, nil,
                        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_SH_ALL, FILE_OPEN, FILE_NON_DIRECTORY_FILE, nil, 0)
 else Result := NtCreateFile(@FileHandle, _DELETE or FILE_WRITE_ATTRIBUTES, pObjAttr, @IoBlock, nil,
                        FILE_ATTRIBUTE_DIRECTORY, 0, FILE_OPEN, FILE_DIRECTORY_FILE, nil, 0);

if Result = STATUS_SUCCESS then
 try
  Result := Nt_DeleteObjectFS(FileHandle, FileAttr);
 finally
  NtClose(FileHandle);
 end;
end;

function Nt_DeleteObjU(const puFileName: PUNICODE_STRING; const cbFileAttr: DWord; const hParentDir: THandle): NTSTATUS;
var
ObjAttr: OBJECT_ATTRIBUTES;
begin
InitializeObjectAttributes(@ObjAttr, puFileName, OBJ_CASE_INSENSITIVE, hParentDir, nil);
Result := Nt_DeleteObject(@ObjAttr, cbFileAttr);
end;

function Nt_DeleteFileU(const puFileName: PUNICODE_STRING; const hParentDir: THandle): NTSTATUS;
var
ObjAttr: OBJECT_ATTRIBUTES;
begin
InitializeObjectAttributes(@ObjAttr, puFileName, OBJ_CASE_INSENSITIVE, hParentDir, nil);
Result := NtDeleteFile(@ObjAttr);
end;

function NtQueryDirectoryFileMem(const FileHandle, Event: THandle; ApcRoutine: Pointer; ApcContext: Pointer;
                                pIoBlock: PIO_STATUS_BLOCK; var pFileInfo: Pointer; var cbFileInfo: DWord;
                                const InfoClass: FILE_INFORMATION_CLASS; ReturnSingleEntry: LongBool;
                                FileName: PUNICODE_STRING; RestartScan: LongBool): NTSTATUS;
begin
Result := NtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, pIoBlock, pFileInfo,
                               cbFileInfo, InfoClass, ReturnSingleEntry, FileName, RestartScan);
while True do
 case Result of
  STATUS_BUFFER_OVERFLOW, STATUS_INFO_LENGTH_MISMATCH:
   begin
    if cbFileInfo > 0 then inc(cbFileInfo, cbFileInfo) else inc(cbFileInfo, QUERY_FILE_FS_INC);
    ReallocMem(pFileInfo, cbFileInfo);
    Result := NtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, pIoBlock, pFileInfo,
                                   cbFileInfo, InfoClass, ReturnSingleEntry,
                                   FileName, Result = STATUS_INFO_LENGTH_MISMATCH);

   end;
  STATUS_PENDING:
   begin
    Assert(False, "NtQueryDirectoryFile   STATUS_PENDING");
    Exit;
   end;
  else Exit;
 end;
end;

function Nt_CreateFile(const pObjName: PUNICODE_STRING; const DesAccess: ACCESS_MASK; const pIoBlock: PIO_STATUS_BLOCK;
                      const pAllocSize: PLARGE_INTEGER; const FileAttr, ShareAccess, CreateDispos, CreateOptions: ULONG;
                      const pRootDir: PHandle; const pSecDecript: PSECURITY_DESCRIPTOR; var FileHandle: THandle): NTSTATUS;
var
ObjAttr: OBJECT_ATTRIBUTES;
begin
if pRootDir <> nil
 then InitializeObjectAttributes(@ObjAttr, pObjName, OBJ_CASE_INSENSITIVE, pRootDir^, pSecDecript)
 else InitializeObjectAttributes(@ObjAttr, pObjName, OBJ_CASE_INSENSITIVE, 0, pSecDecript);
Result := NtCreateFile(@FileHandle, DesAccess, @ObjAttr, pIoBlock, pAllocSize,
                       FileAttr, ShareAccess, CreateDispos, CreateOptions, nil, 0);
end;

const
WIDE_DBL_POINT_DWORD: LongWord    = 3014702; // PDWord(PWideChar(WIDE_DBL_POINT))^

function Us_IsNotEmptyOrRoot(const pName: PWideChar; const NameLen: LongWord): Boolean;
begin
case NameLen of
 0: Result := False;
 1: Result := pName[0] <> ".";
 2: Result := PLongWord(pName)^ <> WIDE_DBL_POINT_DWORD;
 else Result := True;
end;
end;


 
Riply ©   (2008-06-13 17:25) [17]

Вторая часть известного балета :) :

const
DelDirAccess = _DELETE or FILE_DELETE_CHILD or FILE_LIST_DIRECTORY or SYNCHRONIZE;

function Nt_RemoveDirRec(const hDelDir: THandle; DeleteSelf: Boolean): NTSTATUS;
var
IoBlock: IO_STATUS_BLOCK;
pObjInfo: Pointer;
cbObjInfo: DWord;

function _Nt_RemoveDirRec(const hDirecoty: THandle; DelSelf: Boolean): NTSTATUS;
var
 NtNameU: UNICODE_STRING;
 RetStatus, SubFileStatus: NTSTATUS;
 DirHandle: THandle;
 DirAccess: DWord;
 RestartScan: Boolean;
begin
 RestartScan := True;
 Result := STATUS_SUCCESS;
 repeat
  RetStatus := NtQueryDirectoryFileMem(hDirecoty, 0, nil, nil, @IoBlock, pObjInfo, cbObjInfo,
                                       FileDirectoryInformation, True, nil, RestartScan);
  if RetStatus = STATUS_SUCCESS then
   with PFILE_DIRECTORY_INFORMATION(pObjInfo)^ do
    if (FileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
     begin
      Us_InitLen_(@NtNameU, @FileName, FileNameLength);
      if FileAttributes and (FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_SYSTEM) = 0
       then RestartScan := NT_STATUS_SET_WORST(Result, Nt_DeleteFileU(@NtNameU, hDirecoty))
       else RestartScan := NT_STATUS_SET_WORST(Result, Nt_DeleteObjU(@NtNameU, FileAttributes, hDirecoty));
     end
    else
     if Us_IsNotEmptyOrRoot(@FileName, FileNameLength shr SHR_WCHAR) then
      begin
       Us_InitLen_(@NtNameU, @FileName, FileNameLength);
       if FileAttributes and (FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_SYSTEM) = 0
        then DirAccess := DelDirAccess
        else DirAccess := DelDirAccess or FILE_WRITE_ATTRIBUTES;
       SubFileStatus := Nt_CreateFile(@NtNameU, DirAccess, @IoBlock, nil, FILE_ATTRIBUTE_DIRECTORY,
                                      0, FILE_OPEN, FILE_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT,
                                      @hDirecoty, nil, DirHandle);
       if SubFileStatus = STATUS_SUCCESS then
        try
         if DirAccess <> DelDirAccess then _Nt_SetObjAttributes(DirHandle, FILE_ATTRIBUTE_NORMAL);
         RestartScan := NT_STATUS_SET_WORST(Result, _Nt_RemoveDirRec(DirHandle, True));
        finally
         NtClose(DirHandle);
        end
       else
        begin
         RestartScan := False;
         if Result = STATUS_SUCCESS then Result := SubFileStatus;
        end;
      end
     else RestartScan := False
  else
   begin
    NT_STATUS_SET_WORST(Result, RetStatus);
    Break;
   end;
 until RetStatus <> STATUS_SUCCESS;

 if DelSelf then
  if NT_NO_MORE_FILES(Result) then Result := Nt_SetObjDisposInfoDelete(hDirecoty);
end;

begin
cbObjInfo := 1024;
pObjInfo := GetMemory(cbObjInfo);
if pObjInfo <> nil then
 try
  Result := _Nt_RemoveDirRec(hDelDir, DeleteSelf);
 finally
  FreeMem(pObjInfo);
 end
else Result := STATUS_INSUFFICIENT_RESOURCES;
end;

function Nt_RemoveDirRecursivelyU(const pPathForDelete: PUNICODE_STRING; DeleteSelf: Boolean): NTSTATUS;
var
ObjAttr: OBJECT_ATTRIBUTES;
IoBlock: IO_STATUS_BLOCK;
hDirecoty: THandle;
begin
InitializeObjectAttributes(@ObjAttr, pPathForDelete, OBJ_CASE_INSENSITIVE, 0, nil);
if DeleteSelf then
 begin
  Result := NtCreateFile(@hDirecoty, DelDirAccess or FILE_WRITE_ATTRIBUTES, @ObjAttr, @IoBlock, nil,
                         FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_SH_ALL, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT or FILE_DIRECTORY_FILE, nil, 0);
  if Result = STATUS_SUCCESS then Result := _Nt_SetObjAttributes(hDirecoty, FILE_ATTRIBUTE_NORMAL);
 end
else Result := NtCreateFile(@hDirecoty, DelDirAccess, @ObjAttr, @IoBlock, nil,
                            FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_SH_ALL, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT or FILE_DIRECTORY_FILE, nil, 0);
if Result = STATUS_SUCCESS then
 try
  Result := Nt_RemoveDirRec(hDirecoty, DeleteSelf);
 finally
  NtClose(hDirecoty);
 end;
end;


 
Riply ©   (2008-06-13 17:28) [18]

P.S.
Стуктуры выдергивать не стала: и так слишком большой пост получился :)


 
Игорь Шевченко ©   (2008-06-13 18:11) [19]

а то же самое на ассемблере ?


 
Riply ©   (2008-06-13 18:18) [20]

> [19] Игорь Шевченко ©   (13.06.08 18:11)
> а то же самое на ассемблере ?

В этом случае меня бы забанили за злостное засорение форума,
а так грозит только простое :)



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.07.13;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.006 c
15-1211944984
Скарлет
2008-05-28 07:23
2008.07.13
От чего зависит автоматическое вставляние в uses нужных юнитов?


2-1213187618
Patrashitel
2008-06-11 16:33
2008.07.13
Как заставить появиться Popup меню при нажатии левой кнопки мыши?


2-1213159421
DJ Kondakov
2008-06-11 08:43
2008.07.13
Вопрос по TFileStream


15-1211971316
Stas
2008-05-28 14:41
2008.07.13
Рсачет расстояния


15-1211778536
AndreyV
2008-05-26 09:08
2008.07.13
Phoenix приземлился на Марс





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский