Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.01.2025, 16:52   #1
Kronos913
Форумчанин
 
Регистрация: 10.02.2021
Сообщений: 674
По умолчанию Обработка большого файла в 32-битном Delphi

Есть файл, который больше 4 ГБ (если быть точнее, больше максимального LongWord)
Нужно сделать с ним простое побайтное действие (например, "перевернуть" бинарный код - xor 255)

Если считывать символы по одному через blockread - blockwrite - это занимает очень много времени. Тесты даже на файле в 8 мегабайт занимают более минуты. А несколько гигабайт - займёт несколько суток.

Если загрузить файл в TMemoryStream - обработка даже файла на 200 мегабайт прошла мгновенно. Но есть одна проблема - этот метод не сработает для большого файла, который больше чем максимальный LongWord.

Отсюда вопрос: как провести обработку большого файла так, чтобы это НЕ занимало несколько суток
Kronos913 вне форума Ответить с цитированием
Старый 25.01.2025, 17:08   #2
Kronos913
Форумчанин
 
Регистрация: 10.02.2021
Сообщений: 674
По умолчанию

p.s. Я пытался спрашивать нейросеть по этому поводу. Но она, как обычно, дала не рабочий код...
Kronos913 вне форума Ответить с цитированием
Старый 25.01.2025, 19:19   #3
DeepFlake
Форумчанин
 
Регистрация: 16.05.2024
Сообщений: 143
По умолчанию

Не совсем понятно в чём проблема.
BlockRead и BlockWrite созданы как раз для эффективного буферизированного файлового ввода-вывода.

Выделите в программе буфер в 10 мегабайт, считайте данные из файла в него, обработайте буфер, сбросьте буфер в новый файл. и далее в цикле пока всё не обработаете. В чём проблема?

Размер буфера задаётся в Reset и ReWrite.

то есть reset( f, 10*1000000 )
blockread( f, buf, 1 ) - сразу 10 мегабайт считали

Фактический число считанных записей сохраняется в дополнительной переменной RecordsRead. Она будет меньше чем RecordCount, если, например, был достигнут конец файла. (0)

последний блок надо считывать по 1 байту
http://www.delphibasics.ru/BlockRead.php

Последний раз редактировалось DeepFlake; 25.01.2025 в 19:27.
DeepFlake вне форума Ответить с цитированием
Старый 25.01.2025, 19:57   #4
Kronos913
Форумчанин
 
Регистрация: 10.02.2021
Сообщений: 674
По умолчанию

Код:
        fs1:=TFileStream.Create(E[0].Text, fmOpenRead);
        fs2:=TFileStream.Create(E[1].Text, fmCreate);
        st:=TMemorystream.Create;
        d:=fs1.Size;
        while d>0 do begin
          k:=2097152;
          If k>d then k:=d;
          dec(d, k);
          st.Clear;
          st.CopyFrom(fs1, k);
          ShifroStream(r, st);
          fs2.WriteBuffer(st.Memory^, st.Size);
        end;
Получилось заставить такой код работать. Тестирую на архиве в 5 гигабайт. И вот что любопытно.

Изначально я хотел поставить 1 блок размером 16 мегабайт - программа справилась за полторы минуты
Когда же я уменьшил один блок до 2 мегабайт - программа справилась за 56 секунд. Что меня озадачило: почему уменьшение блока ускоряет работу? По идее ж должно быть наоборот.

К слову говоря, снижение до 64 килобайт опять увеличило время работы.
Kronos913 вне форума Ответить с цитированием
Старый 25.01.2025, 20:39   #5
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,867
По умолчанию

ну, осталось экспериментальным путём диаграмму построить Время (Размер блока) и сделать вывод - оптимальные вариант найти, чтоб всем помочь обрабатывать файлы более 4 Гб.
------
а на два куска файл не разрезать, раз Delphi x32?
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.
NetSpace вне форума Ответить с цитированием
Старый 25.01.2025, 20:51   #6
DeepFlake
Форумчанин
 
Регистрация: 16.05.2024
Сообщений: 143
По умолчанию

>очему уменьшение блока ускоряет работу?

блок в 2 мега кэшируется файловой системой в памяти, поэтому
fs2.WriteBuffer(st.Memory^, st.Size); - в реальности ничего не делает.
А когда 16 мег, то fs2.WriteBuffer(st.Memory^, st.Size); реально пишет на диск.

Я так думаю
DeepFlake вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обработка большого количество пользователей. coNsept Общие вопросы .NET 3 30.08.2014 09:14
Как записать верхнее и нижнее слова в 32-битном числе в Delphi? red-eye Помощь студентам 4 07.12.2011 20:47
Обработка большого массива данных Ceme4kin Microsoft Office Excel 3 25.11.2011 13:15
Обработка большого текстового файла и составление по нему отчета erosss Помощь студентам 6 05.05.2010 13:18
Обработка большого кол-ва текстовых данных (Excel 2010) motorway Microsoft Office Excel 9 27.03.2010 00:47