Что нового

ProgressBar для копирования 1 фаила

maxd2007

Новичок
Сообщения
89
Репутация
0
Здравствуйте, никак не могу понять как можно организовать копирование 1 большого фаила (до 4Гб) с прогресс баром, с помощью FileCopy и ProgressOn я так понимаю это не реализовать, т.к невозможно посчитать сколько уже скопировалось, нашел вот такой скрипт:
Код:
_FileCopy("C:\Source", "C:\Dest")

Func _FileCopy($sSource, $sDest, $iShowConfirm=1, $iShowProgress=1)
    Local Const $FOF_RESPOND_YES = 64
    Local Const $FOF_NOCONFIRMATION = 16
    Local Const $FOF_SIMPLEPROGRESS = 256

    Local $iFlags = 0

    If $iShowConfirm = 0 Then $iFlags = BitOR($iFlags, $FOF_NOCONFIRMATION)
    If $iShowProgress <> 0 Then $iFlags = BitOR($iFlags, $FOF_SIMPLEPROGRESS)

    If Not FileExists($sDest) Then DirCreate($sDest)

    Local $oShell = ObjCreate("Shell.Application")

    Local $oNameSpace = $oShell.NameSpace($sDest)
    $oNameSpace.CopyHere($sSource, $iFlags)
EndFunc

Но он не может копировать так _FileCopy ("C:\1\1.img", "J:\12345.img"), с методами объектов я не особо дружу, пробовал читать это Folder.CopyHere method, но как я понял так копируются только фаилы с папками без возможности их переименовать. Мне по сути нужен любой вариант копирования (одного фаила) с обозначением прогреса.
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Код:
Func _FileCopy($fromFile,$tofile)
    Local $FOF_RESPOND_YES = 16
    Local $FOF_SIMPLEPROGRESS = 256
    $winShell = ObjCreate("shell.application")
    $winShell.namespace($tofile).CopyHere($fromFile,$FOF_RESPOND_YES)
EndFunc


Утащил отсюда
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
Видел, но это не подходит, т.к. нельзя сделать так _FileCopy ("C:\1\1.img", "J:\12345.img") т.е. взять фаил 1.img и скопировать его как 12345.img
 

hedji

Продвинутый
Сообщения
409
Репутация
94
А почему нельзя переименовать уже после копирования?
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
По сути Вы правы и даже возразить не могу =), данный вариант даже в голову не лез :-X


Добавлено:
Сообщение автоматически объединено:

И все таки возникают трудности при таком варианте: у меня фаил должен копироваться используя Drag & drop т.е. имя исходного фаила может быть любым, а вот конечный всегда одинаковый и для того, что бы мне правильно переименовать именно тот фаил, который скопировался, мне придется читать строку исходного пути с конца до первого слеша. Может есть вариант проще?


Добавлено:
Сообщение автоматически объединено:

Пока вопрос с именем решил так
Код:
$NameFile = StringRegExpReplace($path, '^.*\\', '')
, может есть способ как то проще скопировать 1 большой фаил с прогресбаром на подобии FileCopy ("c:\1\1.img", "j:\2\2.img"). Т.е. сейчас кусок кода по копированию выглядит так:
Код:
FileDelete ($path_user & "\gmapsupp.img")
$NameFile = StringRegExpReplace($path, '^.*\\', '')
_FileCopy($path,$path_user)
FileMove ($path_user & "\" & $NameFile, $path_user & "\gmapsupp.img")
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Код:
Func _FileCopy($fromFile,$tofile)
    Local $FOF_RESPOND_YES = 16
    Local $FOF_SIMPLEPROGRESS = 256
    $winShell = ObjCreate("shell.application")
    $winShell.namespace($tofile).CopyHere($fromFile,$FOF_RESPOND_YES)
EndFunc

$filename = StringSplit($fromFile, "\")
$newfile = $tofile & "\" & $filename[$filename[0]]
FileMove($newfile, $tofile & "\новое имя файла")
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
лучше использовать управляемые процессы.
маленький набросок
Код:
#include <WindowsConstants.au3>

_Copy('D:\Downloads\Русалочка.avi', @ScriptDir)

Func _Copy($S, $D)
	Local $gs = FileGetSize($S)
	Local $gn = StringRegExpReplace($S, '.*\\', '')
	Local $c = 1048576
	Local $fso = FileOpen($S, 16)
	If $fso = -1 Then Return SetError(1)
	Local $fdo = FileOpen($D & '\' & $gn, 26)
	If $fdo = -1 Then
		FileClose($fso)
		Return SetError(2)
	EndIf
	Local $Form1 = GUICreate("Form1", 528, 100, 276, 158, $WS_SYSMENU)
	Local $Progress1 = GUICtrlCreateProgress(10, 10, 486, 17)
	GUISetState()
	Local $cr, $ext, $alr, $fwr, $prc, $msg
	While 1
;~ 		$msg = GUIGetMsg()
;~ 		Switch $msg
;~ 			Case -3
;~ 				FileClose($fso)                  ; Можно вставить опрос нажатий в окне(пауза, отмена)
;~ 				FileClose($fdo)                  ; это будет немного тормозить процесс копирования, но как вариант управления вполне можно использовать
;~ 				FileDelete($D & '\' & $gn)
;~ 				GUIDelete($Form1)
;~ 		EndSwitch
		$cr = FileRead($fso, $c)
		$ext = @extended
		If $cr = -1 Then ExitLoop
		$alr += $ext
		$fwr = FileWrite($fdo, $cr)
		If Not $fwr Then
			FileClose($fso)
			FileClose($fdo)
			GUIDelete($Form1)
			Return SetError(3)
		EndIf
		$prc = Floor($alr / $gs * 100)
		GUICtrlSetData($Progress1, $prc)
	WEnd
	FileClose($fso)
	FileClose($fdo)
	GUIDelete($Form1)
EndFunc   ;==>_Copy
 
A

Alofa

Гость
Код:
#include <WinAPIFiles.au3>

Local $sFile_1 = @ScriptDir & '\BigFile.rar'
Local $sFile_2 = @ScriptDir & '\CopyDir\File_2.rar'

_FileCopyProgress($sFile_1, $sFile_2, True) ; Третий параметр: False = Не перезаписывть существующий файл
;                                                              True = Перезаписывть существующий файл

Func _FileCopyProgress($iTotalFileSize, $iTotalBytesTransferred, $iFlag)
	Local Static $hProgressProc
	If $hProgressProc Then
		Local $iPercent = Round($iTotalBytesTransferred / $iTotalFileSize * 100)
		ProgressSet($iPercent, ($iPercent = 100) ? 'Выполнено.' : $iPercent & '%')
		Sleep(10)
	Else
		If (Not $iFlag) And FileExists($iTotalBytesTransferred) Then Return 2
		$hProgressProc = DllCallbackRegister('_FileCopyProgress', 'bool', 'uint64;uint64;boolean')
		ProgressOn('_WinAPI_CopyFileEx()', 'Копирование...', '0%')
		If Not _WinAPI_CopyFileEx($sFile_1, $sFile_2, 0, DllCallbackGetPtr($hProgressProc)) Then _
				Return SetError(_WinAPI_GetLastError(), 0, -1)
		DllCallbackFree($hProgressProc)
		$hProgressProc = False
		ProgressOff()
		Return 1
	EndIf
EndFunc   ;==>_FileCopyProgress



Добавлено:
Сообщение автоматически объединено:

Несколько изменил пример.


Добавлено:
Сообщение автоматически объединено:

А в общем-то, что делает Windows при копировании? Правильно, создает новый файл (контейнер), читает копируемый файл и заливает этой информацией второй.
Что и показал joiner в своем примере, только средствами Autoit.
ma:rofl:2007 доработайте строку:
Код:
; Local $fdo = FileOpen($D & '\' & $gn, 26)
Local $fdo = FileOpen($D, 26)

и попробуйте код с копированием в файл с другим именем.
 
Верх