Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.12.2016, 17:40   #1
Maxjuvefan
Пользователь
 
Регистрация: 24.08.2015
Сообщений: 46
По умолчанию Осуществить копирование файлов без замены существующих через функцию SHFileOperation

Здравствуйте. Программа осуществляет копирование всех файлов и папок из одной указанной директории в другую. Копирование осуществляется посредством функции SHFileOperation:

function TMainForm.CopyF(fromDir, toDir: string): boolean;
var
fos: TSHFileOpStruct;
todir2: string;
begin
todir2:=todir;
ZeroMemory(@fos, SizeOf(fos));
with fos do
begin
wFunc := FO_COPY;
//fFlags := FOF_FILESONLY;
fFlags:= FOF_SIMPLEPROGRESS; //Показывать диалог с индикатором прогресса, но не показывать имен файлов
fflags:= fflags or FOF_NOCONFIRMATION; //Отвечает "yes to all" на все запросы в ходе опеации
fflags:= fflags or FOF_SILENT; //Не показывать диалог с индикатором прогресса
pFrom := PChar(fromDir + #0);
pTo := PChar(toDir2);
end;
Result := (0 = ShFileOperation(fos));
end;

Пример использования

CopyF(PChar (RootFolder.FromLabel.Caption), PChar (RootFolder.InLabel.Caption));

Если файл существует, то он будет заменен автоматически. Но мне этого не надо, так как копирование будет происходить автоматически через таймер, и массив файлов со временем будет увеличиваться. Как сделать так, чтобы, если файлы уже существует, то копирование не происходило. Смотрел информацию по fFlags, но нужного не нашел, есть только FOF_RENAMEONCOLLISION - присваивает файлу новое имя при операциях копирования, перемещения или переименования, если файл с указанным именем уже существует, но мне нужно, чтобы он просто не копировался.
Maxjuvefan вне форума Ответить с цитированием
Старый 18.12.2016, 17:45   #2
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Проверку нужно делать If FileExists(файл) then
Aliens_wolfs вне форума Ответить с цитированием
Старый 18.12.2016, 17:49   #3
Maxjuvefan
Пользователь
 
Регистрация: 24.08.2015
Сообщений: 46
По умолчанию

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

Последний раз редактировалось Maxjuvefan; 18.12.2016 в 17:52.
Maxjuvefan вне форума Ответить с цитированием
Старый 18.12.2016, 19:02   #4
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Лови функцию которая копирует все что в папке с проверкой на существующую папку или файл
Код:
  procedure FileDirCopy(srcPath, NewParch : string);

//Функция получающая список файлов и папок
 Procedure ScanDir(StartDir: String; List: TStrings);
Var SearchRec: TSearchRec;
Begin
IF StartDir[Length(StartDir)]<>'\'then StartDir := StartDir + '\';
List.Add(StartDir);
IF FindFirst(StartDir+'*.*',faAnyFile,SearchRec)=0 then Repeat
IF(SearchRec.Attr and faDirectory)<>faDirectory then
List.Add(StartDir+SearchRec.Name);
Until FindNext(SearchRec)<>0;
IF FindFirst(StartDir+'*.*',faAnyFile,SearchRec)=0 then Repeat
IF((SearchRec.Attr and faDirectory)=faDirectory)and
((SearchRec.Name<>'..')and(SearchRec.Name <> '.'))then
ScanDir(StartDir+SearchRec.Name+'\',List);
Until FindNext(SearchRec)<>0;
FindClose(SearchRec);
end;

//Ну и применение этих функций
var
 i: integer;
 Lists: TStringList;
 NewFileDir: string;
 begin
try
Lists:= TStringList.Create;
 ScanDir(srcPath, Lists);
 For i:= 0 to Lists.Count-1 do
 begin
NewFileDir:= StringReplace(Lists[i], srcPath, NewParch, [rfReplaceAll]);
//Проверка на существование папки, если ее нет то создаем
 if not DirectoryExists(ExtractFilePath(NewFileDir)) then
 mkDir(ExtractFilePath(NewFileDir));
//Проверка на существование файла так как true, если его нет то копируем
  CopyFile(PAnsichar(Lists[i]), PAnsichar(NewFileDir), true);
// либо ваша функция c ShFileOperation
if not FileExists(NewFileDir) then
CopyF(Pchar(Lists[i]), Pchar(NewFileDir));
       application.ProcessMessages;
  end;
finally
  Lists.free;
 end;
 end;

//Использование
procedure TForm1.Button2Click(Sender: TObject);
begin
//Из папки в папку
FileDirCopy('C:\111\', 'C:\222\');
end;

Последний раз редактировалось Aliens_wolfs; 19.12.2016 в 07:35.
Aliens_wolfs вне форума Ответить с цитированием
Старый 18.12.2016, 19:26   #5
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
По умолчанию

А копировать папку только с нужной датой религия не позволяет? Просто задать в запись для функции в параметре From путь к этой папке. Система по идеи должна откопировать папку вместе с её содержимым.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Старый 18.12.2016, 19:35   #6
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

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

Последний раз редактировалось Aliens_wolfs; 18.12.2016 в 19:44.
Aliens_wolfs вне форума Ответить с цитированием
Старый 18.12.2016, 21:08   #7
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
По умолчанию

Цитата:
Сообщение от Aliens_wolfs Посмотреть сообщение
Видимо он хочет чтобы не было постоянного копирования файлов которые уже есть.
Еще можно сверять по дате и времени создания файла и размеру, тогда точнее будет, даже с разными именами не будет копировать так как он уже есть, но будет дольше по времени копировать, так как по всем файлам каждый файл проверяеться
Представим. Автоматика ведет некий лог и складывает их папку. Эту папку и её содержимое нужно куда-то отправить. Задача разве не такая? Если нет, тогда просим автора объяснить задачу в деталях. Если да, то просто дайте команду автоматике поступать как в задаче. Пусть складирует в папку: Logs - <дата>. А в конце эту папку достаточно будет откопировать как файл через SHFileOperation. По идеи так же работает Проводник, поэтому если копирует папку, то и копирует файлы и подпапки в ней. Всё очень просто.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Старый 19.12.2016, 01:37   #8
Maxjuvefan
Пользователь
 
Регистрация: 24.08.2015
Сообщений: 46
По умолчанию

Цитата:
Сообщение от саша40 Посмотреть сообщение
Представим. Автоматика ведет некий лог и складывает их папку. Эту папку и её содержимое нужно куда-то отправить. Задача разве не такая? Если нет, тогда просим автора объяснить задачу в деталях. Если да, то просто дайте команду автоматике поступать как в задаче. Пусть складирует в папку: Logs - <дата>. А в конце эту папку достаточно будет откопировать как файл через SHFileOperation. По идеи так же работает Проводник, поэтому если копирует папку, то и копирует файлы и подпапки в ней. Всё очень просто.
Да, допустим, что автоматика ведет некий лог и складывает их в папку Log в подпапку с текущей датой. Эту папку Log необходимо каждую минуту копировать куда-то, так как возможно появление в ней новых файлов. Только нужна проверка на наличие в том месте уже существующих файлов, иначе процесс копирования сильно будет затягиваться. Задача такая.
Maxjuvefan вне форума Ответить с цитированием
Старый 19.12.2016, 01:38   #9
Maxjuvefan
Пользователь
 
Регистрация: 24.08.2015
Сообщений: 46
По умолчанию

Данную задачу я реализовал следующим способом:
Код:
procedure TMainForm.StartCopyClick(Sender: TObject);
var
Files : TStrings;
i, j: integer;
s, s1, s2: string;
begin
  Files:=GetDirList(RootFolder.FromLabel.Caption);
  for i := 0 to Files.Count- 1 do
     begin
     s:=Files[i];
     for j := length(RootFolder.FromLabel.Caption) downto 1 do
     begin
        if s[j-1]= '\' then
        begin
             s2:=copy(RootFolder.FromLabel.Caption, j-1, length(s)-j);
             s1:=Copy(s,0,Pos(s2,s)-1);
             s:=StringReplace(s,s1,RootFolder.InLabel.Caption,
                          [rfReplaceAll, rfIgnoreCase]);
             break;
        end;
     end;
     if not FileExists(s) then
     begin
        CopyF(PChar (RootFolder.FromLabel.Caption), PChar (RootFolder.InLabel.Caption));
     end;
  end;

function TMainForm.GetDirList(const RootDir:String):TStrings;
var
        Directories:TStrings;
        CurrentDirIndex:Integer;
        CurrentDirName,SearchPath,FoundFileName:String;
        R:TSearchRec;
begin
        Directories:=TStringList.Create;
        try
                Result:=TStringList.Create;
                try
                        Directories.Append(RootDir);
                        CurrentDirIndex:=0;
                        repeat
                                CurrentDirName:=IncludeTrailingPathDelimiter(Directories[CurrentDirIndex]);
                                SearchPath:=CurrentDirName+'*.*';
                                if FindFirst(SearchPath,faAnyFile,R)=0 then
                                        try
                                                repeat
                                                        if (R.Name<>'.') and (R.Name<>'..') then
                                                                begin
                                                                        FoundFileName:=CurrentDirName+R.Name;
                                                                        if R.Attr and faDirectory<>0 then Directories.Append(FoundFileName)
                                                                                                     else Result.Append(FoundFileName);
                                                                end;
                                                until FindNext(R)<>0;
                                        finally
                                                FindClose(R);
                                        end;
                                Inc(CurrentDirIndex);
                        until CurrentDirIndex>=Directories.Count;
                except
                        FreeAndNil(Result);
                        raise;
                end;

        finally
                Directories.Free;
        end;
end;
Всем спасибо большое за участие
Maxjuvefan вне форума Ответить с цитированием
Старый 19.12.2016, 07:59   #10
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
По умолчанию

Цитата:
Сообщение от Maxjuvefan Посмотреть сообщение
Да, допустим, что автоматика ведет некий лог и складывает их в папку Log в подпапку с текущей датой. Эту папку Log необходимо каждую минуту копировать куда-то, так как возможно появление в ней новых файлов. Только нужна проверка на наличие в том месте уже существующих файлов, иначе процесс копирования сильно будет затягиваться. Задача такая.
Значит синхронизация. Попробуйте ввести Ini-синхронизатор. Это некий список для синхронизации папок. Можно даже очищать его каждую синхронизацию. Заполнение следующим образом:
Открытие файла-синхронизатора.
Запись файла с данными лога текущего момента времени.
Запись строки в файл-синхронизатор. (Дата, время + Имя записанного файла + возможно какие-либо ещё данные).
Закрытие файла-синхронизации.

При синхронизации запрашиваем именно этот файл(данные из него или сам файл, без разницы).
Считываем в нём данные и копируем только те, которые в нём указаны.
Очищаем файл. Если файл не очищать(например, за сессию или за день), то копировать надо только те файлы, которые после времени начала последней синхронизации).
Закрываем файл-синхронизатор.

Если синхронизация идет на сервер в сети или в сетевой базе данных, то проще дать автоматике команду автоматической отправки логов на сервер. Тут ещё надо сделать временную запись лога в память, если они идут в потоке, чтобы не вызвать Access Violition при попытке доступа к файлу-синхронизатору, если вдруг он занят синхронизацией(вероятность такого довольно мала, ~1-2%, но не далеко нулевая). Последние нужно, если запись идет чисто на жесткий диск.
Принять данное или нет - решать вам. Но предложенный метод требует на 50-60% меньше вычислительных команд, а следовательно времени, для вашей задачи.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Можно ли в Эксель вставлять данные без замены уже существующих? TemaZosin Microsoft Office Excel 12 07.10.2012 23:14
Копирование с SHFileOperation Makin_tosh C++ Builder 0 27.04.2012 04:23
Total Commander копирование файлов без уведомления Ecosasha Софт 2 28.04.2011 20:44
Скоростное копирование файлов через RAM 3D Hunter Общие вопросы Delphi 9 03.07.2009 19:41
Копирование файлов без чтения строк. Alex Cones Общие вопросы Delphi 6 18.04.2009 11:07