purebasic.info

PureBasic forum
Текущее время: Пт янв 19, 2018 10:38 am

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ 1 сообщение ] 
Автор Сообщение
 Заголовок сообщения: Склейка файлов Total Commander'а
СообщениеДобавлено: Пн авг 15, 2011 12:03 pm 
Не в сети
док

Зарегистрирован: Вт июл 17, 2007 1:34 pm
Сообщений: 90
Откуда: Пенза
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Делюсь исходником по склейке файлов, разбитых программой Total Commander. Процедура универсальная, возвращет подробную информацию о текущем выполнении. После выбора первой части файла - обнаруживает остальные, а также crc-файл, если он есть, и использует его данные. Тест сборки файла-образа игры Мафия 2 в Total Commander'e - 17секунд, при использовании этой процедуры - 25секунд ( в это время так же входит удаление файлов с диска). Поэкспериментируйте с размером буфера чтения / записи, он по-умолчанию стоит в 10МБ.
Вот собственно код:
Код:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
EnableExplicit
 
#FILE_BLOCK_SIZE = 10 * 1024 * 1024 ;10МБ
 
;-структура пользовательской переменной для file_stick()
Structure FILE_STICK_PROGRESS
  result.b          ;true - можно забирать результат, false - нельзя
  error.b           ;наличии ошибки выполнения процедуры
  file_delete.b     ;пользовательский флаг true/false удаления исходных файлов
  file_name$        ;текущее имя файла, находящегося в обработке
  file_current.l    ;текущий порядковый номер файла, находящегося в обработке
  file_total.l      ;всего файлов в очереди обработки
  file_percent.l    ;процент завершённости текущего файла (0 - 100)
EndStructure
 
;-перевод из шестнадцатиричной в десятичную с/с
Procedure.q dec(h$)
  Protected r.q, d.q, a$
  h$=UCase(h$)
  For r=1 To Len(h$)
    d<<4 : a$=Mid(h$,r,1)
    If Asc(a$)>60
      d+Asc(a$)-55
    Else
      d+Asc(a$)-48
    EndIf
  Next
  ProcedureReturn d
EndProcedure
 
;-получение свободного места на диске, адрес PathOnDisk$ которому принадлежит
Procedure.q disk_freespace(PathOnDisk$)
  Protected.q space_all, space_total, space_free
  GetDiskFreeSpaceEx_(PathOnDisk$, @space_all, @space_total, @space_free)
  ProcedureReturn space_free
EndProcedure
 
;-склеить файлы
Procedure file_stick(*ProgressVariable.FILE_STICK_PROGRESS)
  Protected file_next_index = 1, i, *file_buffer
  ;;;
  Protected file_selected$, file_mask$, file_output$, file_path$
  Protected file_read, file_write, file_output_size.q, file_output_crc32.l
  ;;;
  NewList   file_part$()
  Protected file_part_block_count, file_part_block_count_double.d, file_part_block_last
  ;;;
  *ProgressVariable\result = #False ;на всякий случай результат
  ;;;получение имени первого файла для сборки
  file_selected$ = OpenFileRequester("Выберите первый файл для сборки", ".001", "*.001|*.001", 0)
  If (file_selected$ = "") Or (FileSize(file_selected$)< 1)
    *ProgressVariable\error = #True
    ProcedureReturn #False  
  EndIf
  ;;;составим маску имени файла (отбросим расширение, а точку оставим)
  file_mask$ = Left(file_selected$, Len(file_selected$) - Len(GetExtensionPart(file_selected$)))
  ;;;проверим, есть ли файл crc, если есть то считаем из него оригинальное имя выходного файла
  ;;;а так же контрольную сумму ожидаемого файла
  If OpenPreferences(file_mask$ + "crc")
    file_output$      = ReadPreferenceString("filename", "")
    file_output_crc32 = dec(ReadPreferenceString("crc32", "0"))
    ;
    ClosePreferences()
  Else
    file_output$ = "[собранный] " + GetFilePart(file_selected$)
  EndIf
  ;;;получаем имя файла результата
  file_output$ = SaveFileRequester("Выберите результирующий файл", file_output$,"Все файлы|*.*|", 0)
  If (file_output$ = "")
    *ProgressVariable\error = #True
    ProcedureReturn #False  
  EndIf
  ;;;;;;;;;;;;;;;
  ;;;;;;;;;;;;;;;
  Protected time = ElapsedMilliseconds()
  ;;;;;;;;;;;;;;;;
  ;;;;;;;;;;;;;;;;
  If (FileSize(file_output$) <> -1)
    MessageRequester("", "Невозможно создать файл"+#CRLF$+file_output$, #MB_OK | #MB_ICONINFORMATION)
    End
  EndIf
  ;;;вычисляем имя следующего файла - *.002, затем *.003 и так далее, пока есть такие файлы
  ;;;и заполняем динамический список таких имён файлов
  While FileSize(file_selected$) > 0
    ;
    AddElement(file_part$())
    file_part$() = file_selected$
    file_output_size + FileSize(file_selected$) ;счётчик размера ожидаемого получаемого файла
    ;
    file_next_index + 1
    file_selected$ = file_mask$ + RSet(Str(file_next_index),3,"0")
  Wend
  ;;;проверяем наличие свободного места на диске получателе
  If (disk_freespace(GetPathPart(file_output$)) < Int(file_output_size * 0.07))
    MessageRequester("", "Недостаточно свободного места на диске получателе!",#MB_OK | #MB_ICONINFORMATION)
    *ProgressVariable\error = #True
    ProcedureReturn #False
  EndIf
  ;;;создаём результирующий файл
  file_write = CreateFile(#PB_Any, file_output$)
  If file_write = #Null
    MessageRequester("", "Невозможно создать файл"+#CRLF$+file_output$, #MB_OK | #MB_ICONINFORMATION)
    End
  EndIf
  ;;;выделяем память под буфер копирования
  *file_buffer = AllocateMemory(#FILE_BLOCK_SIZE)
  If (*file_buffer = #Null)
    *ProgressVariable\error = #True
    ProcedureReturn #False
  EndIf
  ;;;
  *ProgressVariable\file_total   = ListSize(file_part$())
  *ProgressVariable\file_current = 0  
  ;;;проводим копирование по всем файлам
  ForEach file_part$()
    *ProgressVariable\file_current + 1
    *ProgressVariable\file_name$   = file_part$()
    ;
    file_read = ReadFile(#PB_Any, file_part$())
    ;
    file_part_block_count_double = Lof(file_read) / #FILE_BLOCK_SIZE ;дробное значение ожидаемого числа блоков
    file_part_block_count        = Int(file_part_block_count_double) ;целое значение ожидаемого количества блоков (отброшены дробные значения)
    file_part_block_last         = Lof(file_read) - (file_part_block_count * #FILE_BLOCK_SIZE) ;размер остатка (если размер файла не кратен размеру блоку для копирвоания, то получается остаток)
    ;;;если размер файла-отправителя не менее размера одного блока
    If file_part_block_count
      For i = 1 To file_part_block_count ;копируем следующий блок в файл-получатель
        ReadData (file_read,  *file_buffer, #FILE_BLOCK_SIZE)
        WriteData(file_write, *file_buffer, #FILE_BLOCK_SIZE)
        ;;;
        *ProgressVariable\file_percent = Int((i / file_part_block_count) * 100)
        *ProgressVariable\result       = #True ;сигнал о том, что теперь пользователю можно получать результат переменной
      Next
    Else;если же размер файла отправителя меньше размера одного блока то копируем целиком содержимое файла-отправителя в файл-получатель
      ReadData (file_read,  *file_buffer, Lof(file_read))
      WriteData(file_write, *file_buffer, Lof(file_read))
      ;;;
      *ProgressVariable\file_percent = 100
      *ProgressVariable\result       = #True
    EndIf
    ;;;если размер файла-отправителя не кратен размеру одного блока то копируем остаток
    If file_part_block_last
      ReadData (file_read,  *file_buffer, file_part_block_last)
      WriteData(file_write, *file_buffer, file_part_block_last)
      ;;;
      *ProgressVariable\file_percent = 100
      *ProgressVariable\result       = #True
    EndIf
    ;
    CloseFile(file_read)
    ;;;если пользователь указал флаг удаления исходных файлов - удаляем таковые
    If (*ProgressVariable\file_delete)
      DeleteFile(file_part$())
    EndIf
  Next
  ;;;
  ClearList(file_part$())
  FreeMemory(*file_buffer)
  CloseFile(file_write)
  ;;;если указана ненулевая контрольная сумма то проверяем её с контрольной суммой полученного файла
  If (file_output_crc32)
    If (CRC32FileFingerprint(file_output$) <> file_output_crc32)
      MessageRequester("","Полученный файл повреждён! Контрольные суммы не совпадают", #MB_OK | #MB_ICONINFORMATION)
      *ProgressVariable\error = #True
      ProcedureReturn #False
    EndIf
  EndIf
  ;;;если пользователь указал флаг удаления исходных файлов - удаляем crc файл
  If (*ProgressVariable\file_delete)
    DeleteFile(file_mask$ + "crc")
  EndIf
  MessageRequester("", StrF((ElapsedMilliseconds() - time) / 1000) + " секунд", #MB_OK)
  ProcedureReturn #True
EndProcedure
 
 
 
 
Define r.FILE_STICK_PROGRESS
r\file_delete = #True
 
file_stick(@r)
 
 


_________________
purebasic x64


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ 1 сообщение ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB