На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Найти в файле сигнатуру и отрезаць от файла всё что до этой сигнатуры (быстро)
Нужно найти в файле сигнатуру, и отрезать всё что от начала файла до этой сигнатуры, не подскажете каким способом это делается быстрее всего?
Может есть уже какие библиотеки или примеры, компоненты для этого?
Моя реализация на текущий момент через TmemoryStream, но мне кажется что можно быстрее..
Подумать над реализацией двух случаев:
1.Маленький файл (несколько МБ, до гига).
2.Большой файл.
В первом случае - всё прочитать махом в ОЗУ и там ужо найти и выписать хвост. Во втором - читать порциями, аккуратно в них искать сигнатуру (может быть на границе!), выписывать посегментно хвост.

Добавлено
Впрочем, может оказаться, что реализация только 2 варианта (даже с 16 КБ буфером) будет достаточной и быстрее всего. Но может оказаться, что сигнатура очень длинная (скажем, мегабайт), а тогда возникнет ряд проблем. :yes-sad:
Тогда может оцените мой код, по сути нужно найти сигнатуру pdf файла и далее отсечь лишнее, сигнатура всего 4 байта, размер файла ну максимум 10mb, в среднем 1mb.
Меня единственное что смущает так это мой поиск, но как сделать круче не знаю \ не умею ...


ExpandedWrap disabled
    function ExtractPDFFromContainerAndSaveToFile(Stream: TStream; FileName: String; const StartPos: Cardinal = 500): Integer;
    var i: Cardinal; FStream: TStream;
    begin
      i:= StartPos;
      Result := -1;
      while i+4 < Stream.Size do
      begin
        if ( PByteArray(TMemoryStream(Stream).Memory)^[i] = $25) then
            if
               ( PByteArray(TMemoryStream(Stream).Memory)^[i+1] = $50) and
               ( PByteArray(TMemoryStream(Stream).Memory)^[i+2] = $44) and
               ( PByteArray(TMemoryStream(Stream).Memory)^[i+3] = $46)
            then
            begin
              FStream := TFileStream.Create(FileName, fmCreate);
              try
               FStream.WriteBuffer(@PByteArray(TMemoryStream(Stream).Memory)^, i, Stream.Size-i);
              finally
               FStream.Free;
               Result := 0;
              end;
              Exit;
            end;
        Inc(i);
      end;
    end;
Сообщение отредактировано: Jiro -
    Крайне невыгодно 4 раза по одному байту сравнивать (процессорно дорого). Я в Паскале крайне слаб, но точно можно же как-то перевести и сразу Dword'ы сравнить! (но шагать, конечно, всё равно по байтику надо!)
    Jiro, в твоем варианте нет смысла сравнивать побайтно, легче сразу сравнивать с 4-байтным числом. Но ты точно уверен, что сигнатура не будет располагаться, к примеру, с 2-го по 6-й байт?

    Славян
    Зависит от количества ложных срабатываний, возможно, быстрее классически искать первый байт и потом сравнивать хвосты.

    Jiro, 10 мб - это ничто, попробуй заюзать Pos для Ansi строк
    ExpandedWrap disabled
      SetLength(sFile, FileStream.Size);
      FileStream.ReadBuffer(sFile[1], FileStream.Size);
      sSign := RawByteString(#$25#$....);
      p := Pos(sSign, sFile);
    Codero ergo sum
    // Программирую — значит, существую
    Цитата Fr0sT @
    Но ты точно уверен, что сигнатура не будет располагаться, к примеру, с 2-го по 6-й байт?

    Уверен.

    Fr0sT
    размер мусора в среднем 908 байт, ну там плюс\минус, в принципе можно начинать с позиции 500-того байта и буферить гденить 1024 байта и в них искать как вы предложили через Pos, но это итак понятно.

    Но вот тут возник вопрос сам собой, если использовать FileStream.ReadBuffer(sFile[1], FileStream.Size) то это получается
    лишнее копирование из памяти в память, насколько это быстро и затратно по ресурсам и можно ли избежать лишнего копирования передав данные в указатель и потом уже применять Pos?
    Цитата Jiro @
    это получается лишнее копирование из памяти в память

    А копирование и так и так будет. Но оно одно, и от него никуда не деться. Можно, конечно, извратиться через маппинг, но оптимизированной функции поиска по указателю в RTL нет, поэтому смысла в этом немного.
    А какие требования по быстродействию?
    Codero ergo sum
    // Программирую — значит, существую
    Цитата Fr0sT @
    А какие требования по быстродействию?


    Тут требований нету, это я так на будущее узнаю, мало ли пригодится.
    Работа с диском на порядок-три медленнее, чем с памятью, так что скорость будет определяться именно им.
    Кстати, было бы оптимально узнать начальные кластеры файла, а потом ненужные убрать и указать с какого байта начало. Но я технически не знаю, есть ли такая возможность, чтобы у гигабайтного, например, файла отрезать первые пару байт, но при этом не переписывать всё длинное тело?.. :-?
    Славян
    Насколько я понимаю, файл (по крайней мере, в старых файловых системах) стартует с начала кластера, т.е минимальная гранулярность перезаписи от 512 и т.п. байт
    Да, я тоже так думал. Просто это же сильнейшее ограничение, кое могли как-то и побороть. В линухах (в btrfs?) наверняка ж можно!.. Ладно, пустое гадание; надо спецов поспрашивать. :oops:
    Цитата Jiro @
    while i+4 < Stream.Size do

    наверное стоит добавить: while i+4 < Stream.Size-4 - чисто что бы не лезть за границы файлы...
    нечто нейтральное, пока что.
    1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
    0 пользователей:


    [ Script Execution time: 0,1325 ]   [ 20 queries used ]   [ Generated: 23.03.17, 08:07 GMT ]