Как элементарно обработать 1 гиг?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Как элементарно обработать 1 гиг?

Сообщение kibernetics » 03.05.2006 (Ср) 13:51

Привет всем!
У меня возник ступор. А точнее следующая ситуация, у меня есть файл размером 1 гиг. Мне нужно:
1. Удалить с начала файла кусок 0 - 42000Н
2. Удалять через каждые 512 байт блок размером 16 байт. Т.е. изначально блок 528 байт, мне нужно, чтобы от него оставалось 512 байт.

Так вот, я перепробовал 4 разных алгоритма, но такая медленность работы, что ужас. Неужели это действительно так медленно?
1. Сначала я просто удалил блок (0-42000Н), потом сохранил файл. Это заняло около 1 часа! Это делалось, с помощью АПИ-функции от WinHEX'a в визуалБейсике.
2. Если удалять блок через каждые 512 байт, то за ночь! обработалось только ~11Мб. Чушь какая-то.
3. Короче, я остановился на следующем алгоритме:
копирую блок размером 512байт, переключаюсь на другой файл, вставляю, опять перехожу на первый файл, смещаюсь на 516 + 16(те 16, которые мне не нужны) и опять читаю, переключаюсь - вставляю. Так вот за ночь обработалось ~380Мб. Что тоже очень долго.
Я просто хотел узнать, может кто-то сталкивался с обработкой больших файлов? Неужели это и вправду занимает такое большое время? Или алгоритм у меня никудышний? Помогите разобраться... Как можно максимально сократить время для обработки файла такого объема?

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 03.05.2006 (Ср) 14:04

а можно узреть имеющийся код? Что-то не то ты делаешь... При всем ужасе при слове 1 ГБайт это не так уж и много по современным то понятиям

З.Ы. Срочно читай первый топик раздела, а то поздно будет читать!
Весь мир матрица, а мы в нем потоки байтов!

kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Сообщение kibernetics » 03.05.2006 (Ср) 14:10

у меня сейчас такая схема:
For i = 1 To EOF
buf = ww.ReadBytes(512) 'читаем блок в 512 байт
ww.NextObject 'переключаюсь на второй файл
ww.Position = i * 512 - 512 'и перехожу на смещение
ww.WriteBytes buf 'вставляю блок
ww.NextObject снова переключаюсь на обрабатываемый файл
ww.Position = (512 * i) + (i * 16) 'двигаю смещение
Next i

с помощью такого кода за ночь обработалось ~380Mb

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 03.05.2006 (Ср) 14:14

1. а что есть ww?
2. Сей код будет выполнятся для каждого байта открытого файла. Т.е. 1 073 741 824 раз. Многовато пожалуй


З.Ы. что то мне подсказывает что это .NET.
Весь мир матрица, а мы в нем потоки байтов!

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.05.2006 (Ср) 14:23

!Viper! писал(а):2. Сей код будет выполнятся для каждого байта открытого файла. Т.е. 1 073 741 824 раз. Многовато пожалуй


Не обязательно, может быть ф-ция EOF, типа "перегружена" и возвращает FileLen\512
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 03.05.2006 (Ср) 14:29

она конечно может (если это действительно .NET), но что-то мне подсказывает, что вряд ли...
Весь мир матрица, а мы в нем потоки байтов!

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.05.2006 (Ср) 14:32

Если в смысле перегрузки, то в том смысле котором я имел ввиду,
(а я написал "если ф-цтя "типа перегружена" "). то это возможно в обычном ВБ6
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 03.05.2006 (Ср) 14:38

Так.

Что за бред? :?
Чё за for i=1 to EOF? Это типа какой язык?

Автору рекомендуется прийти и прояснить ситуацию. Прочитав http://bbs.vbstreets.ru/viewtopic.php?t=23315 предварительно.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.05.2006 (Ср) 14:42

GSerg писал(а):Так.

Что за бред? :?
Чё за for i=1 to EOF? Это типа какой язык?

Автору рекомендуется прийти и прояснить ситуацию. Прочитав http://bbs.vbstreets.ru/viewtopic.php?t=23315 предварительно.


:lol: Ага, вот поэтому он и ждёт 2 дня, потому что пытается выполнить
For i = 1 to 0 или
For i = 1 to -1

Хотя, конечно, если поизвращаться и сделать локальную ф-цию EOF в форме и вызывать её из этой же формы, то всё понятно...
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.05.2006 (Ср) 14:46

Это что же надо понаписать, чтобы целую ночь работало?
MSDN писал(а):EOF. Returns anInteger containing theBoolean value True when the end of a file opened for Random or sequential Input has been reached.

Цикл от 0 до False. Замечательно.

Я бы сделал примерно так. Не проверял дотошно, может быть наврал с индексами в байтах файлов.
Код: Выделить всё
Option Explicit
Private Declare Function GetTickCount& Lib "kernel32" ()

Private Sub Form_Load()
Dim tmparr() As Byte
Dim flen As Long
Const N As Integer = 10 'число частей
Dim part As Long, rest As Long 'байт в каждой части + остаток
Const CutStart As Long = 270336 '42000h
Dim i As Long
Dim time1 As Long, time2 As Long

time1 = GetTickCount

flen = FileLen("C:\test.iso") - CutStart

part = Fix(flen / N)
rest = flen Mod N
'part*N+rest=flen

'Вырезаем кусок 0-270336
Open "C:\test.iso" For Binary As #1
    Open "C:\test2.iso" For Binary As #2
        For i = 1 To N
            ReDim tmparr(part)
            Get #1, CutStart + 1 + part * (N - 1), tmparr
            Put #2, 1 + part * (N - 1), tmparr
            DoEvents
        Next i
        If rest <> 0 Then
            ReDim tmparr(rest)
            Get #1, flen + CutStart - rest + 1, tmparr
            Put #2, flen - rest + 1, tmparr
        End If
    Close #2
Close #1

'Вырезаем из нового файла из каждого куска по 528 байт 512 байт
flen = FileLen("C:\test2.iso")
ReDim tmparr(512)
Open "C:\test2.iso" For Binary As #1
    Open "C:\result.iso" For Binary As #2
        For i = 1 To flen \ 528
            Get #1, 528 * (i - 1) + 1, tmparr
            Put #2, 512 * (i - 1) + 1, tmparr
            DoEvents
        Next i
    Close #2
Close #1
time2 = GetTickCount&

MsgBox "Процесс занял " & (time2 - time1) / 1000 & " секунд."
End Sub


120 секунд на файл
Explorer писал(а):1,06 ГБ (1 139 734 528 байт)

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.05.2006 (Ср) 14:49

Для отрезания начала разбивал файл на N+1 частей (N полноценных + остаток). Потому что ReDim tmparr(1139734528) говорил "Out of memory". Хотя свободно у меня около 1,7 Гб памяти. Какая там у нас граница выделения памяти? :)

Sirik
Perspicaz
Perspicaz
Аватара пользователя
 
Сообщения: 2280
Зарегистрирован: 19.02.2004 (Чт) 16:09
Откуда: Бердичев, Украина

Сообщение Sirik » 03.05.2006 (Ср) 15:03

какой тип имеет tmparr?
возьми размер типа умнож на 1139734528, получается не слишком мало

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 03.05.2006 (Ср) 15:06

О горе мне!!! :oops: EOF c LOF спутал... Хотя конечно первым спутал автор

З.Ы, А интересно длину какого файла он таким образом пытался определить. Нумера файла то у него нет
Весь мир матрица, а мы в нем потоки байтов!

kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Сообщение kibernetics » 03.05.2006 (Ср) 15:10

ww. -это от апи-враппера WihHEX
вот весь код:
Sub must()
Dim ww As Wrapper
Dim i As Long
Set ww = New Wrapper

ww.OpenObject "i:\out2\out.bin", ModeInPlace
ww.OpenObject "i:\out2\sum.bin", ModeReadOnly
EOF = ww.Size
For i = 1 To EOF 'EOF - end of file
buf = ww.ReadBytes(512)
ww.NextObject
ww.Position = i * 512 - 512
ww.WriteBytes buf
ww.NextObject
ww.Position = (512 * i) + (i * 16)

Next i
ww.NextObject
ww.SaveCurrent

Set ww = Nothing
End Sub

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.05.2006 (Ср) 15:10

!Viper! писал(а):О горе мне!!! :oops: EOF c LOF спутал... Хотя конечно первым спутал автор

З.Ы, А интересно длину какого файла он таким образом пытался определить. Нумера файла то у него нет


ИМХО, автор ничего не спутал, а просто в последнее время стало модно придумывать какую-то свою функцию EOF, которая возвращает не ДА/НЕТ, а номер последнего байта файла.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.05.2006 (Ср) 15:13

этот пост бессмысленный, т.к. я не заметил EOF=ww.size
Последний раз редактировалось Хакер 03.05.2006 (Ср) 15:30, всего редактировалось 2 раз(а).
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 03.05.2006 (Ср) 15:26

тогда мои предположения о количестве проходов по коду были верными... Действительно цикл выполняется 1 073 741 824 раз. Это во первых. Во вторых buf похоже имеет тип Variant, что скорость тоже не убыстряет... Ну и куча других нюансов, типа определения позиции чтения через i довершают процесс замедления проги до черепашьей скорости
Весь мир матрица, а мы в нем потоки байтов!

kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Сообщение kibernetics » 03.05.2006 (Ср) 15:30

вот это да!
код от Amed занял 551,437 секунд. файл размером 1107025925 байт. проц атлон 2.6/256 памяти.
я четыре дня бился с этим апи-враппером. тормоза жуть. а файлы такого объёма очень часто нужно обрабатывать. думаю, что уже наверное быстрее и невозможно сделать. ну разве что может чуть быстрее... но всё равно 4 дня против 552 секунд..., я даже бы час согласился. уж очень нужна была реализация... преогромнейшее спасибо всем форумчанам, особенно Amed. теперь флешки будут быстрее восстанавливаться :)

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.05.2006 (Ср) 15:44

Sirik, обрати внимание. У меня тип Byte. 1 байт.

kibernetics, проверь-таки код, прежде чем копипастить. А то флешки будут быстрее портить данные :)

Насчет сделать быстрее - запросто можно, если не делать промежуточный файл с отрезанным началом. Как минимум. Ну и крохи прилизать.
Код: Выделить всё
Option Explicit
Private Declare Function GetTickCount& Lib "kernel32" ()

Private Sub Form_Load()
Dim tmparr() As Byte
Dim flen As Long
Const N As Integer = 10 'число частей
Dim part As Long, rest As Long 'байт в каждой части + остаток
Const CutStart As Long = 270336 '42000h
Dim i As Long
Dim time1 As Long, time2 As Long

time1 = GetTickCount

'Вырезаем из нового файла из каждого куска по 528 байт 512 байт
flen = FileLen("C:\test.iso") - CutStart
ReDim tmparr(512)
Open "C:\test.iso" For Binary As #1
    Open "C:\result.iso" For Binary As #2
        For i = 1 To flen \ 528
            Get #1, CutStart + 528 * (i - 1) + 1, tmparr
            Put #2, 512 * (i - 1) + 1, tmparr
            DoEvents
        Next i
    Close #2
Close #1
time2 = GetTickCount&

MsgBox "Процесс занял " & (time2 - time1) / 1000 & " секунд."
End Sub

Тот же файл сделался за 96 секунд. Скорость обработки почти 11 Мб/сек.

kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Сообщение kibernetics » 03.05.2006 (Ср) 16:20

Amed
да, действительно, зачем отрезать начало, если всё равно то что нужно сливается в новый файл. ступил. можно же просто сделать офсет на 42000 и читать...
но всё равно мне очень нравится как оно работает. быстро :), не могу нарадоваться. просто, в микросхеме флеш-памяти организация немного по-другому сделана, нежели обычно. там кластер - 512 байт еще сопровождается информационным блоком в 16 байт, итого 528. так вот чтобы привести дамп флешки в читабельный раздел, как на винте, нужно повырезать эти информационные блоки. но я уже проверил - данные на флехе восстановились, значит код работает!

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 03.05.2006 (Ср) 16:39

kibernetics, ты не оговорил в самом начале, нужен ли промежуточный файл с отрезанным началом :)
Не нужен - так и шут с ним.

kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Сообщение kibernetics » 04.05.2006 (Чт) 10:04

а как работает файл-маппер? я как-то видел на си подобную вещь. работает на космической скорости. типа файл в памяти, но физически размещен на диске. можно ли такое же реализовать в ВБ? это нужно для осуществления поиска в байтах.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 04.05.2006 (Чт) 10:51

Сделать такое можно. Подробности в MSDN. Ключевые слова CreateFileMapping, MapViewOfFile, OpenFileMapping.

З.Ы. Собственно делал я как то такую штуку, можно покопаться в исходниках и выложить в "Кирпичи", например
Весь мир матрица, а мы в нем потоки байтов!

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.05.2006 (Чт) 11:12

Щас проверил - маппить придётся кусочками, обидно, я думал операционка сама с этим вопросом разберётся...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Сообщение kibernetics » 04.05.2006 (Чт) 11:13

!Viper!
да уж, если действительно выложить твою реализацию маппера на бейсике в кирпичи, то несомненно это повлечет новый уровень решения сложных задач на басике. думаю, с нынешними объемами информации это будет весьма полезным и востребованным решением. ведь в том же си маппинг используется достаточно активно. а вот лично мне, допустим, нравится басик и уходить с него на си я бы не хотел. басик везде применим. даже если нет под рукой девелоперской платформы, как нужна для си, то даже в вба можно быстро сварганить какой-то полезный алгоритм, тобишь автоматизировать процесс.

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Сообщение pronto » 05.05.2006 (Пт) 4:47

Может кого и заинтересует...
Переписал код Amed'а на PowerBasic'e и оформил его в виде dll. Работает быстро :o , а вот правильно ли - решит kibernetics.
Вложения
reduceDump.rar
Сама dll + ее исходник + простенький примерчик ее использования из VB
(11.08 Кб) Скачиваний: 102
O, sancta simplicitas!


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot, Google-бот и гости: 189

    TopList  
cron