purebasic.info

PureBasic forum
Текущее время: Вт июл 17, 2018 5:59 pm

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




Начать новую тему Ответить на тему  [ Сообщений: 17 ]  На страницу 1, 2  След.
Автор Сообщение
СообщениеДобавлено: Ср окт 11, 2017 9:28 pm 
Не в сети
профессор

Зарегистрирован: Пн янв 03, 2011 4:27 pm
Сообщений: 410
Благодарил (а): 5 раз.
Поблагодарили: 17 раз.
Пункты репутации: 0
Есть архив, в нем нужно заменить определенный файл, не пересобирая весь архив заново.
Я набросал пример(процедура PackagingFiles и участки PAK1, PAK2), но он, мне, не нравится, чего-то(и за работы с памятью).

Можете поделится идеями, советами, примерами кода?
P.S. архивы игры занимают от 1 до 8 GB, и грузить в память 2-6 GB, как-то не хочется.
Сам код:
Код:
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
;{
Enumeration
  #ZOLO_NumberFiles
  #ZOLO_NumberFiles1
  #ZOLO_ReadMemFiles
  #ZOLO_CreateFiles
  #ZOLO_SaveBin
  #ZOLO_OpenBin
  #ZOLO_UnpackingFiles
  #ZOLO_PackagingFiles
EndEnumeration
 
Structure Header_Archiver
  Header.s{8}
  Number.l
  Version.l
EndStructure
 
Structure Header_Files
  ID_Files.l
  OffsetFiles.l
  SizeFiles.l
EndStructure
;}
 
Procedure NumberFiles(Directory.s)
  If ExamineDirectory(#ZOLO_NumberFiles, Directory, "*.*")  
    While NextDirectoryEntry(#ZOLO_NumberFiles)
      If DirectoryEntryType(#ZOLO_NumberFiles) = #PB_DirectoryEntry_File      
        iNumber_Return + 1
      EndIf
    Wend
    FinishDirectory(#ZOLO_NumberFiles)
  EndIf
  ProcedureReturn iNumber_Return
EndProcedure
 
Procedure CreateFiles(CreateArchiver.s, Directory.s)
  If CreateFile(#ZOLO_CreateFiles, CreateArchiver)
    ;{
    *H_Arc.Header_Archiver = AllocateStructure(Header_Archiver)
   
    *H_Arc\Header = "Archiver"
    *H_Arc\Version = 1
    iNumber.l = NumberFiles(Directory)
    *H_Arc\Number = iNumber
    WriteData(#ZOLO_CreateFiles, *H_Arc, SizeOf(Header_Archiver))
   
    Dim HF.Header_Files(iNumber)
   
    iLenFiles.l = iNumber * SizeOf(Header_Files)
   
    WriteData(#ZOLO_CreateFiles, @HF(), iLenFiles)
   
    iOffsetLen.l = Lof(#ZOLO_CreateFiles)
   
    ;}
    ;{
    iNumber_Return.l = 0
    If ExamineDirectory(#ZOLO_NumberFiles1, Directory, "*.*")  
      While NextDirectoryEntry(#ZOLO_NumberFiles1)
        If DirectoryEntryType(#ZOLO_NumberFiles1) = #PB_DirectoryEntry_File  
          ;{
          iNumber_Return1.l = 1+iNumber_Return
          HF(iNumber_Return)\ID_Files = iNumber_Return1
          HF(iNumber_Return)\OffsetFiles = iOffsetLen
          iSizeFiles.l = DirectoryEntrySize(#ZOLO_NumberFiles1)
          HF(iNumber_Return)\SizeFiles = iSizeFiles
          iOffsetLen+iSizeFiles
          iDirectory.s = Directory+DirectoryEntryName(#ZOLO_NumberFiles1)
          ;}
          ;{
          If ReadFile(#ZOLO_ReadMemFiles, iDirectory)
            ilength.l = Lof(#ZOLO_ReadMemFiles)                          
            *MemoryID = AllocateMemory(ilength)        
            If *MemoryID
              ReadData(#ZOLO_ReadMemFiles, *MemoryID, ilength)  
              WriteData(#ZOLO_CreateFiles, *MemoryID, ilength)
            EndIf
            FreeMemory(*MemoryID)
            CloseFile(#ZOLO_ReadMemFiles)
          EndIf
          ;}
          iNumber_Return + 1
        EndIf
      Wend
      FinishDirectory(#ZOLO_NumberFiles1)
    EndIf
    ;}
    FileSeek(#ZOLO_CreateFiles, SizeOf(Header_Archiver))
    WriteData(#ZOLO_CreateFiles, @HF(), iLenFiles)
   
    CloseFile(#ZOLO_CreateFiles)
  Else
    MessageRequester("Information","may not create the file!")
  EndIf
EndProcedure
 
Procedure SaveBin(iSaveFiles.s, iOffset.l, iSize.l, id_File.l)  
  If CreateFile(#ZOLO_SaveBin, iSaveFiles)
    FileSeek(id_File, iOffset)
    *MemoryID = AllocateMemory(iSize)
    ReadData(id_File, *MemoryID, iSize)
    WriteData(#ZOLO_SaveBin, *MemoryID, iSize)
    FreeMemory(*MemoryID)
    CloseFile(#ZOLO_SaveBin)                      
  Else
    MessageRequester("Information","may not create the file!")
  EndIf
EndProcedure
 
Procedure OpenBin(iOpenFiles.s, iOffset, id_File.l)  
  If ReadFile(#ZOLO_OpenBin, iOpenFiles)
    FileSeek(id_File, iOffset)
    iSize.l = Lof(#ZOLO_OpenBin)
    *MemoryID = AllocateMemory(iSize)
    ReadData(#ZOLO_OpenBin, *MemoryID, iSize)
    WriteData(id_File, *MemoryID, iSize)
    FreeMemory(*MemoryID)
    CloseFile(#ZOLO_OpenBin)                      
  Else
    MessageRequester("Information","OpenBin may not create the file!")
  EndIf
EndProcedure
 
Procedure UnpackingFiles(UnpackingFiles.s)
  If ReadFile(#ZOLO_UnpackingFiles, UnpackingFiles)
    ;{
    *U_Arc.Header_Archiver = AllocateStructure(Header_Archiver)
    ReadData(#ZOLO_UnpackingFiles, *U_Arc, SizeOf(Header_Archiver))
    Debug *U_Arc\Header
    Debug *U_Arc\Version
    Debug "----------------"
    ;}
    ;{    
    Dim DATA_Files.Header_Files(*U_Arc\Number)
    Len_UFiles.l = (*U_Arc\Number * SizeOf(Header_Files))
    *MemoryID_UFiles  =  AllocateMemory(Len_UFiles)
    ReadData(#ZOLO_UnpackingFiles, *MemoryID_UFiles, Len_UFiles)  
    CopyMemory(*MemoryID_UFiles, DATA_Files(), Len_UFiles)  
    FreeMemory(*MemoryID_UFiles)
    ;}
    ;{
    For t=0 To *U_Arc\Number-1
      Debug DATA_Files(t)\ID_Files
      SaveBin(GetPathPart(UnpackingFiles)+Str(DATA_Files(t)\ID_Files)+".bin", DATA_Files(t)\OffsetFiles, DATA_Files(t)\SizeFiles, #ZOLO_UnpackingFiles)
    Next
    ;}
    CloseFile(#ZOLO_UnpackingFiles)              
  Else
    MessageRequester("Information","Couldn't open the file!")
  EndIf
EndProcedure
 
Procedure PackagingFiles(OpenFile.s, PackagingFiles.s, ID_Files.l)
  If OpenFile(#ZOLO_PackagingFiles, OpenFile)
    ;{
    *P_Arc.Header_Archiver = AllocateStructure(Header_Archiver)
    ReadData(#ZOLO_PackagingFiles, *P_Arc, SizeOf(Header_Archiver))
    Debug *P_Arc\Header
    Debug *P_Arc\Version
    ;}
    ;{
    Dim DATA_Files.Header_Files(*P_Arc\Number)
    Len_PFiles.l = (*P_Arc\Number * SizeOf(Header_Files))
    *MemoryID_UFiles  =  AllocateMemory(Len_PFiles)
    ReadData(#ZOLO_PackagingFiles, *MemoryID_UFiles, Len_PFiles)  
    CopyMemory(*MemoryID_UFiles, DATA_Files(), Len_PFiles)  
    FreeMemory(*MemoryID_UFiles)
    Debug DATA_Files(ID_Files-1)\ID_Files
    Debug "----------------"
    ;}  
    ;{
    ;- PAK1
    iOffsetEND.l = DATA_Files(ID_Files-1)\OffsetFiles + DATA_Files(ID_Files-1)\SizeFiles
    iLengthFiles.l = Lof(#ZOLO_PackagingFiles)
    iOffsetLength.l = iLengthFiles-iOffsetEND
    FileSeek(#ZOLO_PackagingFiles, iOffsetEND)
    ;}    
    ;{
    ;- PAK2
    *ID_mem = AllocateMemory(iOffsetLength)  
    ReadData(#ZOLO_PackagingFiles, *ID_mem, iOffsetLength)
    FileSeek(#ZOLO_PackagingFiles, DATA_Files(ID_Files-1)\OffsetFiles)
    TruncateFile(#ZOLO_PackagingFiles)
    OpenBin(PackagingFiles, DATA_Files(ID_Files-1)\OffsetFiles, #ZOLO_PackagingFiles)
    WriteData(#ZOLO_PackagingFiles, *ID_mem, iOffsetLength)
    ;}
   
    iNewOffsetLen.l = DATA_Files(ID_Files-1)\OffsetFiles
    iNewSizeFiles.l = FileSize(PackagingFiles)
   
    iNewOffsetLen1.l = iNewSizeFiles-DATA_Files(ID_Files-1)\SizeFiles
 
    Debug iNewOffsetLen1
    DATA_Files(ID_Files-1)\SizeFiles = iNewSizeFiles
   
  ;  iNewOffsetLen+iNewSizeFiles
   
    For t = ID_Files To *P_Arc\Number-1
     
     DATA_Files(t)\OffsetFiles = DATA_Files(t)\OffsetFiles + iNewOffsetLen1
      ;DATA_Files(t)\OffsetFiles = iNewOffsetLen
    ;  iNewOffsetLen + DATA_Files(t)\SizeFiles    
    Next
     FileSeek(#ZOLO_PackagingFiles, SizeOf(Header_Archiver))
     WriteData(#ZOLO_PackagingFiles, @DATA_Files(), Len_PFiles)
 
    FreeMemory(*ID_mem)
    CloseFile(#ZOLO_PackagingFiles)              
  Else
    MessageRequester("Information","Couldn't open the file!")
  EndIf
EndProcedure
 
Directory.s = "1\"
CreateArchiver.s = "Text.Arc"    
;PackagingFiles.s = "Text2_1.bin"
PackagingFiles.s = "Text2_2.bin"
ID_Files.l = 2
 
CreateFiles(CreateArchiver, Directory)
 
PackagingFiles(CreateArchiver, PackagingFiles, ID_Files)
 
UnpackingFiles(CreateArchiver)
 



Последний раз редактировалось @ZOLO@ Пт окт 13, 2017 12:30 am, всего редактировалось 1 раз.

Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Чт окт 12, 2017 9:05 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Сб мар 28, 2015 11:06 pm
Сообщений: 139
Откуда: Україна
Благодарил (а): 7 раз.
Поблагодарили: 10 раз.
Пункты репутации: 4
@ZOLO@
1. если новые файлы не превышают размер старых - то просто перезаписываешь изменённые данные (нули в конце)
2. если новые файлы превышают размер старых - то новые данные пишешь в конец и правишь OffsetFiles, SizeFiles

ты весь архив в память грузишь или чё там много памяти должно есть? в код не вникал


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 12:29 am 
Не в сети
профессор

Зарегистрирован: Пн янв 03, 2011 4:27 pm
Сообщений: 410
Благодарил (а): 5 раз.
Поблагодарили: 17 раз.
Пункты репутации: 0
LinXP писал(а):
2. если новые файлы превышают размер старых - то новые данные пишешь в конец и правишь OffsetFiles, SizeFiles
не вариант, размер файла может увеличится, и за 1-6 байт записывать в конец, как-то не выгод.
LinXP писал(а):
ты весь архив в память грузишь или чё там много памяти должно есть?
нет, только ту часть, которая не подверглась изменению. Посмотри процедура PackagingFiles и участки PAK1, PAK2.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 7:33 am 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 300
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Трудно судить не зная структуру обрабатываемой информации, но для хранения часто меняющихся порций я бы использовал обособленную упаковку/распаковку в памяти каждой из них и хранение их(упакованных порций) в блобах sqlite с автоматической(https://www.techonthenet.com/sqlite/auto_vacuum.php) или принудительной по необходимости упаковкой(уже не порций а всего файла базы) средствами субд.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 2:06 pm 
Не в сети
профессор

Зарегистрирован: Пн янв 03, 2011 4:27 pm
Сообщений: 410
Благодарил (а): 5 раз.
Поблагодарили: 17 раз.
Пункты репутации: 0
jobless писал(а):
но для хранения часто меняющихся порций я бы использовал обособленную упаковку/распаковку в памяти каждой из них и хранение их(упакованных порций) в блобах sqlite с автоматической(https://www.techonthenet.com/sqlite/auto_vacuum.php) или принудительной по необходимости упаковкой(уже не порций а всего файла базы) средствами субд.
Не вариант, у каждой чужой игры свой архив, и под него надо написать программу распаковку и упаковку.
jobless писал(а):
Трудно судить не зная структуру обрабатываемой информации
В первом сообщений, есть пример процедуры упаковки CreateFiles.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 3:00 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 300
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Что значит не вариант?
Я правильно понимаю, что нужно несколько файлов собрать в один.
А потом по какому то критерию заменить только часть файлов-частей в файле-ранее вобравшем в себя всех.
Кстати совсем не вижу упаковки в смысле сжатия, они (файлы) уже сжаты и дальше нет смысла пытаться?

сколько файлов, мин-макс их размер?
суммарный размер объединения?

p.s. ...архивы игры занимают от 1 до 8 GB ... это про суммарный объём или про части которые нужно собирать в одну кучу?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 4:03 pm 
Не в сети
профессор

Зарегистрирован: Пн янв 03, 2011 4:27 pm
Сообщений: 410
Благодарил (а): 5 раз.
Поблагодарили: 17 раз.
Пункты репутации: 0
jobless писал(а):
Я правильно понимаю, что нужно несколько файлов собрать в один.
Нет, нужно файл, заменить другим, который может быть больше или меньше оригинала.
jobless писал(а):
Кстати совсем не вижу упаковки в смысле сжатия, они (файлы) уже сжаты и дальше нет смысла пытаться?
В игре, для которой я пишу распаковщик и упаковщик, файлы сжимаются Zip и помещаются в архив.
jobless писал(а):
p.s. ...архивы игры занимают от 1 до 8 GB ... это про суммарный объём или про части которые нужно собирать в одну кучу?
Один файл(архив) в игре, может занимать размер 1-14 gb.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 4:29 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 300
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Мы как французы с немцами на англоязычном форуме )))

Заменить в файле архива созданного кем то или всё таки созданного нами ранее из нескольких файлов?

и определимся файл это часть
Архив это все

так вот от 1 до 14гб это возможные размеры частей или архива?
И сколько этих частей может быть?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 6:02 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Сб мар 28, 2015 11:06 pm
Сообщений: 139
Откуда: Україна
Благодарил (а): 7 раз.
Поблагодарили: 10 раз.
Пункты репутации: 4
@ZOLO@ писал(а):
не вариант, размер файла может увеличится, и за 1-6 байт записывать в конец, как-то не выгод.

тогда это единственный, относительно "быстрый" вариант... использую редко, когда лень всю структуру трогать или на больших файлах

ps: в твоём случае наверное было бы проще написать скрипт под QuickBMS и заюзать функу recreate

jobless писал(а):
так вот от 1 до 14гб это возможные размеры частей или архива?
И сколько этих частей может быть?

да сколько угодно, вот для примера http://s019.radikal.ru/i609/1709/f3/ae590b6206db.jpg


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 7:05 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 300
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Вижу на скрине кучу мелких файлов и поэтому ещё меньше понимаю суть проблемы.
Предположить могу только одно, архив о котором идёт речь формирует кто то другой и работает кто другой с ним в последующем и значит мы не вольны менять его структуру.

Если это не так, то и sqlite c блобами и аналог того как в xbase memo поля хранят прекрасно подходят для замены, удаления, добавления фрагментов(файлов) в архив и масса других реализаций....


Последний раз редактировалось jobless Пт окт 13, 2017 7:10 pm, всего редактировалось 1 раз.

Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 7:08 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Сб мар 28, 2015 11:06 pm
Сообщений: 139
Откуда: Україна
Благодарил (а): 7 раз.
Поблагодарили: 10 раз.
Пункты репутации: 4
jobless на скрине левая игра, просто для примера больших и разнообразных файлов, к теме значения не имеет


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 7:13 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 300
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
так я и не пойму чего то самого главного! Изначально я понял что нужно собрать много файлов в один и затем заменять только часть из них и поторяю, вариантов реализации полно, вопрос только в размере составных частей, т.е. можно с ними как с цельными кусками в памяти работать или они заведомо могут оказаться больше чем доступно оперативной памяти.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 7:57 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Сб мар 28, 2015 11:06 pm
Сообщений: 139
Откуда: Україна
Благодарил (а): 7 раз.
Поблагодарили: 10 раз.
Пункты репутации: 4
jobless не насколько я понял это не мультиархив, и задача поменять кусок данных (которые больше оригинала, хоть на байт или больше) где нибудь в большом файле и есть в данном случае три варианта:
1. читать кусками весть оригинал (и хедеры и дату), менять и писать в новый файл - долго, надо дополнительное место на диске
2. "переместиться" до изменённого участка, подготовить необходимое место для новых данных, переместив данные которые находятся ниже на определённое количество байт. вписать новые данные - не так долго как первый вариант, но сложнее в реализации и возможно понадобится много памяти
3. добавить в конец новые данные и поправить парочку байт координат где то в файле - вроде быстрее чем предыдущие варианты.. - возни меньше, ресурсов не много..


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 8:06 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 300
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Я пока не получил ответа на главный вопрос: Структура архива задана из вне и запрещено менять ее?

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт окт 13, 2017 8:25 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Сб мар 28, 2015 11:06 pm
Сообщений: 139
Откуда: Україна
Благодарил (а): 7 раз.
Поблагодарили: 10 раз.
Пункты репутации: 4
jobless структура задана разработчиком игры, менять нельзя, если её поменять - игра разумеется не запустится


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

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


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

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


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

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