Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » AutoIt » Скрипт для разбиения файла на части

Ответить
Настройки темы
Скрипт для разбиения файла на части

Пользователь


Сообщения: 135
Благодарности: 32

Профиль | Отправить PM | Цитировать


Изменения
Автор: Diamond
Дата: 31-08-2009
Описание: Изменения в коде пакетного файла
Скрипт позволяет разбивать файл на части, которые в последствии можно объеденить с помощью пакетного
файла без нарушения внутреннего форматирования (см. команда Copy /?).
После разбиения, скрипт создаёт пакетный файл "Combine all parts.bat" в том же директории куда копируются части.
P.S. Надеюсь это кому нибудь пригодится.
читать дальше »
Код: Выделить весь код
#include <WinAPI.au3>
#include <GuiConstants.au3>
#include <WindowsConstants.au3>
#include <GuiStatusBar.au3>
Global $Title = "SplitFile", $Msg, $ret, $fSplitRunning
Global $Gui = GUICreate($Title, 500, 240)
GUICtrlCreateLabel("Путь к файлу:", 5, 10, 104, 22)
GUICtrlCreateLabel("Сохранить в:", 5, 50, 104, 22)
GUICtrlCreateLabel("Размер части:", 5, 90, 104, 22)
Global $Input1 = GUICtrlCreateInput("",110, 10, 300, 22, 0x0080)
    GUICtrlSetTip(-1, "Путь к файлу-источнику.")
Global $Input2 = GUICtrlCreateInput("C:\Split",110, 50, 300, 22, 0x0080)
    GUICtrlSetTip(-1, "Директорий для сохранения частей.")
Global $Input3 = GUICtrlCreateInput("", 110, 90, 300, 22, 0x2000+0x0080)
    GUICtrlSetTip($Input3, "Размер каждой части в Мегабайтах.")
Global $Button1 = GUICtrlCreateButton("Обзор", 420, 10, 70, 22)
Global $Button2 = GUICtrlCreateButton("Обзор", 420, 50, 70, 22)
Global $Button3 = GUICtrlCreateButton("Разделить", 420, 140, 70, 40)
For $i = $Input1 To $Input3
    GUICtrlSetFont($i-3, 11.5, 800, 0, "Times New Roman")
    GUICtrlSetFont($i, 11.5, 500, 0, "Arial")
Next
Global $radio1 = GUICtrlCreateRadio("Bytes", 10, 140, 50, 20)
Global $radio2 = GUICtrlCreateRadio("KBytes", 10, 160, 60, 20)
Global $radio3 = GUICtrlCreateRadio("MBytes", 10, 180, 60, 20)
    GUICtrlSetState($radio3, $GUI_CHECKED)
Global $Progress = GUICtrlCreateProgress(0, 0, -1, -1, 0x01)
Global $hProgress = GUICtrlGetHandle($Progress)
Global $aParts[4] = [1, 222, 270, -1]
Global $hStatusBar = _GUICtrlStatusBar_Create($Gui, $aParts), $fStatusBarSpoiled = False
_GUICtrlStatusBar_EmbedControl($hStatusBar, 1, $hProgress, 4)
_GUICtrlStatusBar_SetText($hStatusBar, "0%", 2)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
        Exit
    Case $Button1
        GUISetState(@SW_DISABLE, $Gui)
        $ret = FileOpenDialog($Title, "", 'Все файлы (*.*)', 1, "", $Gui)
        If Not @error Then GUICtrlSetData($Input1, $ret)
        GUISetState(@SW_ENABLE, $Gui)
    Case $Button2
        GUISetState(@SW_DISABLE, $Gui)
        $ret = FileSelectFolder("Выберите пустой директорий для сохранения частей.", "", 1, "", $Gui)
        If Not @error And FileExists($ret) Then GUICtrlSetData($Input2, $ret)
        GUISetState(@SW_ENABLE, $Gui)
    Case $Button3
        If Split() = -1 Then $fSplitRunning = False
    Case $radio1
        GUICtrlSetTip($Input3, "Размер каждой части в Байтах.")
    Case $radio2
        GUICtrlSetTip($Input3, "Размер каждой части в Килобайтах.")
    Case $radio3
        GUICtrlSetTip($Input3, "Размер каждой части в Мегабайтах.")
    EndSwitch
WEnd

Func Split()
    $fSplitRunning = True ; Флаг $fSplitRunning сообщает о том что функция Split была запущена или завершена
    Local $ret, $sFile, $sDir, $iSplitSize, $aDirInfo, $iSize, $i, $PartCount, $Current, $newState, $oldState
    Local $iBytes, $tBuffer, $hFileOpen, $hFileWrite, $sExt, $sFileName, $sBat
    If @ScriptDir <> @WorkingDir Then FileChangeDir(@ScriptDir)
    $sFile = GUICtrlRead($Input1)
    $sDir = GUICtrlRead($Input2)
    For $i = $radio1 To $radio3
        If GUICtrlRead($i) = $GUI_CHECKED Then ExitLoop
    Next
    $iSplitSize = GUICtrlRead($Input3)*1024^($i-$radio1)
    If Not FileExists($sFile) Then
        _MsgBox(16, $Title, "Файл не существует.", $Gui)
        Return -1
    EndIf
    If Not FileExists($sDir) Then
        If Not DirCreate($sDir) Then
            _MsgBox(16, $Title, "Укажите путь к папке.", $Gui)
            Return -1
        EndIf
    Else
        $aDirInfo = DirGetSize($sDir, 1)
        If $aDirInfo[1]+$aDirInfo[2] > 0 Then
        $ret = _MsgBox(16, $Title, "Указанная папка не пуста.", $Gui)
        Return -1
    EndIf
    EndIf
    If DriveGetType($sDir) <> "Fixed" Then
        _MsgBox(16, $Title, "Указанный тип носителя не поддерживается.", $Gui)
        Return -1
    EndIf
    If Not $iSplitSize Then
        _MsgBox(16, $Title, "Установлено недопустимое значение размера для части.", $Gui)
        Return -1
    EndIf
    $iSize = FileGetSize($sFile)
    If $iSplitSize >= $iSize Then
        _MsgBox(16, $Title, "Указанный размер, превышает или равен размеру файла.", $Gui)
        Return - 1
    EndIf
    ;===============================================
    $PartCount = Ceiling($iSize/$iSplitSize)
    $sDir = StringRegExpReplace($sDir,"\\$","") & "\"
    $sFileName = StringRegExpReplace($sFile,"^.*\\","")
    $sExt = "." & StringRegExpReplace($sFileName, "^.*\.|^.*","")
    _GUICtrlStatusBar_SetText($hStatusBar, "Открытие файла...", 3)
    $hFileOpen = _WinAPI_CreateFile($sFile, 2, 2)
    $Current = $iSplitSize
    _GUICtrlStatusBar_SetText($hStatusBar, "Разделение...", 3)
    For $i = 1 To $PartCount
        If $i = $PartCount Then $Current = $iSize-$iSplitSize*($i-1)
        $tBuffer = DllStructCreate("byte[" & $Current & "]")
        _WinAPI_ReadFile($hFileOpen, DllStructGetPtr($tBuffer), $Current, $iBytes)
        $hFileWrite = _WinAPI_CreateFile($sDir & "part" & $i & $sExt, 1, 4)
        _WinAPI_WriteFile($hFileWrite, DllStructGetPtr($tBuffer), $Current, $iBytes)
        _WinAPI_CloseHandle($hFileWrite)
        _WinAPI_SetFilePointer($hFileOpen, 0, 1) ; смещение от текущей позиции на указанный размер($Current)
        $newState = Round(100*$i/$PartCount)
        If $newState <> $oldState Then
            GUICtrlSetData($Progress, $newState)
            _GUICtrlStatusBar_SetText($hStatusBar, $newState & "%", 2)
            $oldState = $newState
        EndIf
    Next
    _WinAPI_CloseHandle($hFileOpen)
    $sBat = StrBatCreate($sExt, $sFileName, $PartCount)
    FileWrite($sDir & "Combine all parts.bat", $sBat)
    GUICtrlSetData($Progress, $newState)
    _GUICtrlStatusBar_SetText($hStatusBar, "100%", 2)
    Sleep(400)
    GUICtrlSetData($Progress, 0)
    _GUICtrlStatusBar_SetText($hStatusBar, "0%", 2)
    _GUICtrlStatusBar_SetText($hStatusBar, "Готово", 3)
    Return -1
EndFunc

Func StrBatCreate($sExt, $sDestFile, $iCount)
    Local $sBat
    $sBat = '@echo off' & @LF & _
    'title Подготовка...' & @LF & _
    'setlocal enableextensions enabledelayedexpansion' & @LF & _
    'set strTempFolder=$temp%random%' & @LF & _
    'md ".\%strTempFolder%"' & @LF & _
    'for /l %%i in (1,1,' & $iCount & ') do (set strPartFile=Part%%i'& $sExt & @LF & _
    'if exist "!strPartFile!" (move "!strPartFile!" ".\%strTempFolder%\!strPartFile!">nul))' & @LF & _
    'title Слияние...' & @LF & _
    'copy /b ".\%strTempFolder%\Part*'& $sExt & '" "' & $sDestFile & '"' & @LF & _
    'title Пожалуйста, дождитесь завершения...' & @LF & _
    'move ".\%strTempFolder%\Part*'& $sExt & '" ".">nul' & @LF & _
    'rd /s /q ".\%strTempFolder%"'
    Return CharToOem($sBat)
EndFunc

Func WM_COMMAND($HWnd, $MsgID, $wParam, $lParam)
    Local $iFile, $CtrlID, $iSplitSize, $i, $iPartCount, $iFileSize
    $CtrlID  = BitAND($wParam, 0xFFFF)
    Switch $CtrlID
        Case $Button1 To $Button3
        If $fSplitRunning Then
            DllCall("User32.dll", "int", "MessageBeep", "uint", 16)
            Return 1
        EndIf
        Case $Input1, $Input3, $radio1 To $radio3
        $iFile = GUICtrlRead($Input1)
        If FileExists($iFile) And Not $fSplitRunning Then
            For $i = $radio1 To $radio3
                If GUICtrlRead($i) = $GUI_CHECKED Then ExitLoop
            Next
            $iSplitSize = Number(GUICtrlRead($Input3)*1024^($i-$radio1))
            $iFileSize = FileGetSize($iFile)
            $iPartCount = Ceiling($iFileSize/$iSplitSize)
            If $iPartCount < 0 Or $iFileSize <= $iSplitSize Then $iPartCount = 0
            _GUICtrlStatusBar_SetText($hStatusBar, "Кол-во частей: " & $iPartCount, 3)
        EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_PAINT($HWnd, $MsgID)
    If $fStatusBarSpoiled Then ; "перерисовка" StatusBar
        _GUICtrlStatusBar_EmbedControl($hStatusBar, 1, $hProgress, 4)
        $fStatusBarSpoiled = False
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_SYSCOMMAND($HWnd, $MsgID, $wParam, $lParam)
    Local Const $SC_RESTORE = 0xF120
    ;Устанавливаю флаг $fStatusBarSpoiled в True (для WM_PAINT это обозначит что StatusBar был неверно отрисован при разворачивании окна.)
    If $wParam = $SC_RESTORE Then $fStatusBarSpoiled = True
    Return $GUI_RUNDEFMSG
EndFunc

Func _MsgBox($MsgBoxType, $MsgBoxTitle, $MsgBoxText, $Main_GUI)
    Local $ret, $err
    GUISetState(@SW_DISABLE, $Main_GUI)
    $ret = DllCall("user32.dll", "int", "MessageBox", _
            "hwnd", $Main_GUI, _
            "str", $MsgBoxText, _
            "str", $MsgBoxTitle, _
            "int", $MsgBoxType)
    $err = @error
    GUISetState(@SW_ENABLE, $Main_GUI)
    If Not $err Then Return $ret[0]
EndFunc   ;==>_MsgBox

Func CharToOem($String)
    Local $tBuffer = DllStructCreate('char[' & StringLen($String)+1 & ']')
    DllCall('user32.dll','none','CharToOem','str',$String,'ptr',DllStructGetPtr($tBuffer))
    If @error Then Return SetError(@error, 0, 0)
    Return SetError(0, 0, DllStructGetData($tBuffer, 1))
EndFunc

-------
Создатель знает, что достиг совершенства не когда нечего добавить, а когда нечего убрать. - Антуан де Сент-Экзюпери

Это сообщение посчитали полезным следующие участники:

Отправлено: 09:00, 29-08-2009

 

Аватара для FlatX007

Ветеран


Сообщения: 553
Благодарности: 87

Профиль | Отправить PM | Цитировать


Ничё так... молодец! сам придумал ?

PS. Каскрась код в цветной (утилита Au3ToPst)

Отправлено: 13:54, 29-08-2009 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

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


Аватара для Medic84

$AutoITer


Автор проектов


Сообщения: 446
Благодарности: 44

Профиль | Отправить PM | Цитировать


FlatX007, Если он разукрасит этот код, то у него возникнет ошибка. Слишком много символов для размещения на форуме
Только не вижу смысла в создании других MSgBox и FileOpenDialog Объясните зачем, а?

-------

AutoIT Русское сообщество| Моя лаборатория


Отправлено: 13:59, 29-08-2009 | #3


Пользователь


Сообщения: 135
Благодарности: 32

Профиль | Отправить PM | Цитировать


Цитата FlatX007:
Ничё так... молодец! сам придумал ? »
Спасибо! Код мой, а идея... где-то я уже видел нечто подобное раньше.
Цитата Medic84:
Только не вижу смысла в создании других MSgBox и FileOpenDialog Объясните зачем, а? »
FileOpenDialog - просто нравиться, MSgBox был нужен как дочерний, для того чтобы запретить доступ к основному Gui.

-------
Создатель знает, что достиг совершенства не когда нечего добавить, а когда нечего убрать. - Антуан де Сент-Экзюпери


Отправлено: 14:30, 29-08-2009 | #4


Аватара для FlatX007

Ветеран


Сообщения: 553
Благодарности: 87

Профиль | Отправить PM | Цитировать


Цитата Medic84:
Только не вижу смысла в создании других MSgBox и FileOpenDialog Объясните зачем, а? »
Они не другие ... FileOpenDialog это взято из "Инклюды" WinAPI.au3
_WinAPI_GetOpenFileName() строка ~3101

Да только непонятно зачем это #include <WinAPI.au3>

Отправлено: 14:32, 29-08-2009 | #5


Пользователь


Сообщения: 135
Благодарности: 32

Профиль | Отправить PM | Цитировать


Да, думаю действитель лучше убрать их (лишние запчасти) а про штатный MsgBox я совсем забыл что там последний параметр это hwnd окна. - Сегодня исправлю.
Цитата FlatX007:
Да только непонятно зачем это #include <WinAPI.au3> »
Так ведь из неё используются функции для чтения и записи в файл.

-------
Создатель знает, что достиг совершенства не когда нечего добавить, а когда нечего убрать. - Антуан де Сент-Экзюпери


Отправлено: 14:42, 29-08-2009 | #6


Пользователь


Сообщения: 135
Благодарности: 32

Профиль | Отправить PM | Цитировать


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

-------
Создатель знает, что достиг совершенства не когда нечего добавить, а когда нечего убрать. - Антуан де Сент-Экзюпери


Отправлено: 16:31, 29-08-2009 | #7


Аватара для SyDr

Старожил


Сообщения: 215
Благодарности: 62

Профиль | Отправить PM | Цитировать


Цитата Diamond:
Так ведь из неё используются функции для чтения и записи в файл. »
А стандартные возможности языка не подходят?


И ещё, почему бы не создавать папку, вместо того, чтобы писать, что она не сущесвтует. И почему она обязательно должна ыбть пуста?

-------

"Что мы думаем, знаем или во что верим в конце концов не так уж и важно.
Важно лишь то, что мы делаем."
Джон Раскин


Отправлено: 16:46, 29-08-2009 | #8


Пользователь


Сообщения: 135
Благодарности: 32

Профиль | Отправить PM | Цитировать


Цитата SyDr:
А стандартные возможности языка не подходят? »
А там в любом случае есть необходимость в использовании функции _WinAPI_SetFilePointer, а штатной замены насколько я знаю для неё нет.
Цитата SyDr:
И ещё, почему бы не создавать папку, вместо того, чтобы писать, что она не сущесвтует. »
Спасибо. Хороший совет.
Цитата SyDr:
И почему она обязательно должна ыбть пуста? »
Туда может копироваться большое количество частей, я думаю, так будет удобней в ней ориентироваться. Кроме того я не могу гарантировать корректную работу пакетного файла поскольку в нём используются подставные символы. В общем, чем меньше в папке посторонних файлов тем надёжнее.

-------
Создатель знает, что достиг совершенства не когда нечего добавить, а когда нечего убрать. - Антуан де Сент-Экзюпери


Отправлено: 17:08, 29-08-2009 | #9


Аватара для SyDr

Старожил


Сообщения: 215
Благодарности: 62

Профиль | Отправить PM | Цитировать


Цитата Diamond:
А там в любом случае есть необходимость в использовании функции _WinAPI_SetFilePointer, а штатной замены насколько я знаю для неё нет. »
Код: Выделить весь код
3.3.1.0 (20th May, 2009) (Beta)
- Added #135: FileSetPos(), FileGetPos() functions for moving the file pointer around.
В бетах уже есть

-------

"Что мы думаем, знаем или во что верим в конце концов не так уж и важно.
Важно лишь то, что мы делаем."
Джон Раскин


Отправлено: 18:34, 29-08-2009 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » AutoIt » Скрипт для разбиения файла на части

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Нужен скрипт для autoit для раскопирования файла irk72ag Автоматическая установка приложений 3 19-06-2009 15:27
Мультимедиа - [решено] Программа для разбиения mp3 по папкам arseniiavr Программное обеспечение Windows 4 06-02-2009 22:42
подгрузка части кода на html-страницу из отдельного файла shmond Вебмастеру 3 04-04-2007 16:43
Скрипт для поиска файла Pavlov10 Программирование и базы данных 3 02-03-2006 11:51
Как собрать 2 части avi-файла в один? mitino Хочу все знать 7 08-11-2003 00:14




 
Переход