Конференция "Начинающим" » Посоветуйте библиотеку для Delphi
 
  • Larin © (10.04.18 10:11) [0]
    Для быстрой работы с содержимым файла. Например, нужно открыть файл и быстро найти все вхождения определенной подстроки (или определенной последовательности байтов). Пример: формат файла неизвестен, но в файле в разных частях записаны JPEG-и и нужно их все извлечь (ищем FF D8 FF E0)

    Спасибо заранее.
  • aka © (10.04.18 10:20) [1]
    Читать файл блоками от начала до конца и считать вхождения.
  • Larin © (10.04.18 10:20) [2]
    Ищем все FF D8, при этом тут же находя концовку FF D9
  • Larin © (10.04.18 10:21) [3]

    > aka ©   (10.04.18 10:20) [1]


    каков размер блока?
  • aka © (10.04.18 10:25) [4]

    > вхождения определенной подстроки (или определенной последовательности
    > байтов)

    Это две разные вещи.
  • kilkennycat © (10.04.18 13:26) [5]

    >  (ищем FF D8 FF E0)

    вообще-то, не гарантирует, что это джпег. а так - [1] и никаких библиотек тут не надо.
  • Larin © (10.04.18 17:35) [6]

    > aka ©   (10.04.18 10:20) [1]
    > Читать файл блоками от начала до конца и считать вхождения.
    >


    А если возникнет такая ситуация: читаем блоками на 1024 байт и ищем подстроку "Hello my little world". А она попадает частично в один блок, а частично - в следующий.

    Как быть?
  • KilkennyCat © (10.04.18 18:08) [7]

    > читаем блоками на 1024 байт и ищем подстроку "Hello my little world". А она попадает частично в один блок, а частично
    > - в следующий.
    >
    > Как быть?

    увеличить блок вдвое. если читать по 2048 байт, то "Hello my little world" точно влазит целиком
  • aka © (10.04.18 18:13) [8]

    > А если возникнет такая ситуация: читаем блоками на 1024
    > байт и ищем подстроку "Hello my little world". А она попадает
    > частично в один блок, а частично - в следующий.
    >
    > Как быть?

    В [4] - ре ж писал, ты либо ищешь строки либо байты. Потому что грубо говоря строка может быть в разных кодировках, отсюда и байтами разными она будет кодироваться
  • aka © (10.04.18 18:19) [9]

    > увеличить блок вдвое. если читать по 2048 байт, то "Hello
    > my little world" точно влазит целиком

    Ну тоже не вариант. Например блок заканчивается на "Hello ", следующий начинается на "my little world" в алгоритме это нужно предусмотреть
  • kilkennycat © (10.04.18 18:37) [10]
    тогда 4096. теперь точно влезет, нутром чую.
  • aka © (10.04.18 18:56) [11]

    > тогда 4096.

    ну так скорее всего.
  • Dimka Maslov © (11.04.18 23:43) [12]
    По одному читать надо. По одному.
  • SergP © (12.04.18 17:12) [13]
    Читаем 2 блока, ищем. Когда прошли первый блок, грузим третий, прошли второй блок - грузим четвертый и т.д.
  • Redmond (13.04.18 10:50) [14]
    > Посоветуйте библиотеку для Delphi

    гм? Не думаю что такие есть...

    > А если возникнет такая ситуация: читаем блоками на 1024
    > байт и ищем подстроку "Hello my little world". А она попадает
    > частично в один блок, а частично - в следующий.
    > Как быть?


    Ватсон? Ну это же элементарно! Вы знаете номер блока? Вы знаете позицию блока? Знаете позицию в которой предположительно найдено совпадение? Просто вычислить новое смещение же! :)

    > тогда 4096. теперь точно влезет, нутром чую.

    Академики шутить изволят? С:
    Увеличение размера блока лишь уменьшают вероятность, но не исключают её. С таким подходом единственный вариант гарантированно исключить попадание на границу - тупо прочитать файл целиком. :3

    > Ищем все FF D8, при этом тут же находя концовку FF D9

    Нюансы для размышлений: FF D8 - вовсе не обязательно начало файла JPEG, FF D9 - вовсе не обязательно конец файла JPEG, FF D8 и FF D9 могут попасться и в самом (остальном) файле и вообще не иметь отношения к JPEG.

    P.S. http://pda.delphimaster.net/?id=1459559016&n=7
  • kilkennycat © (13.04.18 20:14) [15]

    > С таким подходом единственный вариант гарантированно исключить
    > попадание на границу - тупо прочитать файл целиком. :3

    и это есть верное решение. и вся библиотека искомая - TFileStream да небольшая оптимизация поиска, реализация которой зависит от условий. Например, если ищем вхождение FF D8 и только его, то нет смысла читать побайтово, можно через один. Если искать строго FF D8 FF E0,  то можно читать лишь каждый 4-ый байт, что сокращает время тормознутых файловых операций.
    А вообще, по поиску паттернов и поиску вообще существует масса литературы. Например, полезно начать с https://www.livelib.ru/author/19753/latest-dzhulian-baknell
  • Redmond (13.04.18 20:44) [16]
    Верное? Весь файл? Ну допустим что в теории может и так, но на практике появляются проблемы вида - например файл весом 20+ гигов как-то не очень получится прочитать целиком.

    TFileStream это не библиотека... В случае с JPEG полагаю сперва надо искать FF, а уже при нахождении делать всякие дополнительные вещи.
  • Redmond (13.04.18 20:55) [17]
    Писал я утилиту с целевой этой самой == "Нетбук, 1GB DDR2, WinXP" - там если пытаться читать из файла блоками больше 256 метров - уже нехилые проблемы вылазили, а файлы гигабайтами мерялися.
  • SergP © (13.04.18 21:05) [18]

    > С таким подходом единственный вариант гарантированно исключить
    > попадание на границу - тупо прочитать файл целиком.


    А почему нельзя поблочно читать?
    если строка поиска не превышает размер блока, то выделяем буфер размером в 2 блока, и читаем туда блоки, бегаем кругами по буферу и ищем... Прочесали один блок, и сразу же на его место грузим очередной.
  • Redmond (13.04.18 21:27) [19]
    Можно и нужно. Это просто этакой ответ предыдущим человекам, которые силялися всё решить лишь увеличением буфера. (%

    Алгоритм желательно изначально проектировать так, чтоб размер буфера можно было легко менять (буквально одним действием, хотя бы константой в коде), и чтоб работало даже если задать размер буфера "1 байт". :3

    Зачем два блока? Всё равно заранее не определить понадобится ли второй, а всегда читать по два будет накладным. хотя... Может зависеть от задачи, надо обмозговать.
 
Конференция "Начинающим" » Посоветуйте библиотеку для Delphi
Есть новые Нет новых   [134427   +34][b:0.001][p:0.001]