Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/25: Рейтинг темы: голосов - 25, средняя оценка - 4.68
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908

Функция поиска offset по hex значению в бинарном файле

03.03.2023, 20:41. Показов 7950. Ответов 77

Всем доброго времени суток.
По названию темы понятно, наверное, что надо сделать.
Начал своё дело с написания функции, которая конвертирует из hex в byte
C++
1
2
3
4
5
6
7
8
9
10
static vector<uint8_t> hex2byte(const char *hex) {
    char high, low;
    vector<uint8_t> buf(strlen(hex) / 2);
    for (int i = 0, length = strlen(hex); i < length; i += 2) {
        high = toupper(hex[i]) - '0';
        low = toupper(hex[i + 1]) - '0';
        buf[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
    }
    return buf;
}
Теперь осталось написать функцию поиска, которая бы возвращала бы найденный offset
Но для Windows и Linux нет одного метода.
Для Linux можно использовать mmap, а вот для Windows что?
Хотелось бы использовать один и тот же быстрый инструмент.
Так как работа связана с большими файлами и поиск надо будет делать, как с начала так и с конца файла, да ещё и на слабых машинах, где ОЗУ < размера обрабатываемого файла, то mmap на Linux вряд ли поможет.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.03.2023, 20:41
Ответы с готовыми решениями:

Замена hex данных в бинарном файле
Здравствуйте. Не особо этим интересовался. По факту хочу автоматизировать одну задачу. Но не знаю как в delphi работать с бинарными...

Функции поиска в бинарном файле
Задание: Есть структура с именем worker с полями: name - фамилия и инициалы; position - должность; year - год поступления на...

Функции поиска в бинарном файле по номеру записи
1) Считывание данных в массив структур из текстового файла structures.txt (он прикреплен). 2) Запись данных в бинарный файл. Структура...

77
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
31.03.2023, 23:58
blackeangel, а передать (char*)&vector[0] ?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
01.04.2023, 00:34
Цитата Сообщение от blackeangel Посмотреть сообщение
Нужно либо конвертировать как то, либо переписывать hex2byte
Вариант 1) У вектора есть метод data(). Не надо конвертировать.

Вариант 2) Можно просто переделать мою функцию так, чтобы она принимала vector<char> - это делается элементарно.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
01.04.2023, 10:53  [ТС]
DrOffset,
У вектора есть метод data(). Не надо конвертировать.
при
C++
1
2
std::vector<uint8_t> data = hex2byte(whatfind);
std::size_t off = findOffsetInFile(fin, 256, data.data(), sizeof data);
Говорит, что не знает функцию findOffsetInFile

Вариант 2 не рассматривается, потому что char array правильная подача на эту функцию, с моей точки зрения.

SmallEvil,
(char*)&vector[0]
Мысль хорошая, но как её размер передать. Заметьте, что функция принимает и данные и размер данных...
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
01.04.2023, 11:34
Цитата Сообщение от blackeangel Посмотреть сообщение
Заметьте, что функция принимает и данные и размер данных...
Цитата Сообщение от blackeangel Посмотреть сообщение
Говорит, что не знает функцию findOffsetInFile
C++
1
2
std::vector<uint8_t> data = hex2byte(whatfind);
std::size_t off = findOffsetInFile(fin, 256, (char*)data.data(), data.size());
Добавлено через 1 минуту
blackeangel, возьмите себе за правило тщательно изучать документацию и интерфейс тех средств, которыми вы пользуетесь. Это избавит от многих вопросов в будущем.

Добавлено через 6 минут
Цитата Сообщение от blackeangel Посмотреть сообщение
Вариант 2 не рассматривается, потому что char array правильная подача на эту функцию, с моей точки зрения.
Грамотное решение, чтобы одновременно сохранить и C-интерфейс и получить типобезопасность, которую дает контейнер - это сделать перегрузку:
C++
1
2
3
4
5
6
7
8
9
std::size_t findOffsetInFile(std::FILE* file, std::size_t size, char const* bytes, std::size_t len)
{
//// реализация из прошлых постов
}
 
std::size_t findOffsetInFile(std::FILE* file, std::size_t size, std::vector<char> const& bytes)
{
    return findOffsetInFile(file, std::size_t size, bytes.data(), bytes.size());
}
А ваша функция пусть сразу возвращает std::vector<char> и не std::vector<uint8_t>, от этого вы ничего не потеряете.
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
02.04.2023, 22:53  [ТС]
DrOffset, всё отлично работает, спасибо.
А как изменить что б поиск шёл с конца файла?
А для того чтобы переделать в надо вместо return добавлять в вектор, например, а потом его возвращать?

Добавлено через 1 минуту
Просто у меня по задумке опционально: по умолчанию поиск с начала и первое совпадение, поиск с конца и первое совпадение, и поиск всех совпадений
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
03.04.2023, 18:20  [ТС]
Опечатался в вопросе.
Для того чтобы найти все совпадения надо return заменить на добавление в вектор? Ну и функцию переделать, чтоб она возвращала вектор, соответственно...
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
04.04.2023, 20:45  [ТС]
DrOffset, сделал чтоб искал все совпадения и первое. Как сделать чтобы искал с конца?!
Кликните здесь для просмотра всего текста
C++
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
std::vector<size_t> findOffsetInFile(std::FILE* file, std::size_t size, char const* bytes, std::size_t len, int metod_find=0)
{
    /*
    metod_find=0 - first find
    metod_find=1 - all finds
    metod_find=-1 - reverse first find ?!
     */
    std::unique_ptr<char[]> buffer( new char[size + len] );
    std::vector<size_t> sxs;
    std::size_t tSize = 0; // Total read bytes
 
    char* sBuf = &buffer[0];
    std::size_t fSize = std::fread(sBuf, 1, size, file);
    if(fSize >= len)
    {
        if(char* pFnd = (char*)::memmem(sBuf, fSize, bytes, len))
        {
            if(metod_find == 0){
                sxs.push_back(std::distance(sBuf, pFnd));
                return sxs;
            }
            if(metod_find == 1){
                sxs.push_back(std::distance(sBuf, pFnd));
            }
        }
        tSize += fSize;
        std::memcpy(sBuf, sBuf + fSize - len, len);
 
        char* pBuf = &buffer[len];
        while(std::size_t sSize = std::fread(pBuf, 1, size, file))
        {
            // Also here is the processing of the buffer boundary
            char* pFnd = (char*)::memmem(sBuf, sSize + len, bytes, len);
            if(pFnd)
            {
                if(metod_find == 0){
                    sxs.push_back(tSize + std::distance(sBuf, pFnd));
                    break;
                }
                if(metod_find == 1){
                    sxs.push_back(tSize + std::distance(sBuf, pFnd));
                }
            }
            if(sSize < len)
            {
                break; // There's no point to continue lookup
            }
            tSize += sSize;
            std::memcpy(sBuf, pBuf + sSize - len, len);
        }
    }
    return sxs; // Not found or error
}
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
04.04.2023, 20:50
Цитата Сообщение от blackeangel Посмотреть сообщение
Как сделать чтобы искал с конца?!
Пока нет возможности код писать. Если через пару дней будет актуально еще, то дам решение.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
04.04.2023, 20:56  [ТС]
DrOffset, конечно будет актуально. Поиск информации ни к чему хорошему не привёл. Поиск с конца файла что то не очень любят...
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
11.04.2023, 14:58  [ТС]
DrOffset, всё ещё актуально
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
12.04.2023, 12:00
Лучший ответ Сообщение было отмечено blackeangel как решение

Решение

Цитата Сообщение от blackeangel Посмотреть сообщение
всё ещё актуально
C++
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
std::size_t findBackwardOffsetInFile(std::FILE* file, std::size_t size, char const* bytes, std::size_t len)
{
    if(std::fseek(file, 0L, SEEK_END) != 0)
    {
        return -1;
    }
    std::size_t const fileSize = std::ftell(file);
    std::size_t const buffSize = size + len;
 
    std::unique_ptr<char[]> buffer( new char[buffSize] );
 
    char* sBuf = &buffer[0];
    std::size_t offset = fileSize - std::min(fileSize, buffSize);
 
    while(std::fseek(file, offset, SEEK_SET) == 0)
    {
        std::size_t cSize = std::fread(sBuf, 1, buffSize, file);
        if(cSize < len)
        {
            break;
        }
        if(char* pFnd = (char*)::memmem(sBuf, cSize, bytes, len))
        {
            std::rewind(file);
            return offset + std::distance(sBuf, pFnd);
        }
        if(offset == 0)
        {
            break;
        }
        offset -= (offset - cSize != 0) ? cSize - len : cSize;
    }
    std::rewind(file);
    return -1;
}


Тут осталась одна особенность, которую надо исправить. memmem все еще ищет в прямом порядке. Т.е. надо заменить ее вызов на нечто, что будет искать с конца буфера. Остальной код не поменяется.
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
12.04.2023, 12:04  [ТС]
DrOffset, не, менять не надо, всё так. Мы идём с конца файла, а ищем в прямой последовательности. А не в обратной.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
12.04.2023, 12:13
blackeangel, просто если задача этого поиска найти самое последнее вхождение последовательности, то этот код выдаст неверный результат, если в файле например вот так:
Code
1
2
3
4
// ищем EB EF, размер буфера, например, 10 байт
 
// в файле (в конце):
XX XX EB EF 00 00 EB EF 00 00
Код найдет первый EB EF, а не последний EB EF, вопреки интуитивному ожиданию.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
12.04.2023, 14:48  [ТС]
DrOffset, нет, задача найти самое первое, но с конца файла

Добавлено через 2 минуты
DrOffset, то есть мы читаем в буфер с конца файла, по буферу идёт прямой поиск...

Добавлено через 2 часа 8 минут
DrOffset, понял, про что вы имели в виду. Если буфер большой и в него помещается несколько искомых значений, то тогда он выдаст первое найденное в буфере. Вы об этом? Тогда как костыльное решение может быть это использование размера буфера равное 2 длины искомого, ТК буфер же из 2х частей..

Добавлено через 18 минут
DrOffset,
Т.е. надо заменить ее вызов на нечто, что будет искать с конца буфера.
std::search не подойдёт?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
12.04.2023, 17:06
Цитата Сообщение от blackeangel Посмотреть сообщение
Вы об этом?
Да.

Цитата Сообщение от blackeangel Посмотреть сообщение
Тогда как костыльное решение может быть это использование размера буфера равное 2 длины искомого, ТК буфер же из 2х частей..
Лучше все-таки искать с конца.

Цитата Сообщение от blackeangel Посмотреть сообщение
std::search не подойдёт?
Скорее std::find_end подойдет.

Добавлено через 1 час 1 минуту
blackeangel,
C++
1
2
3
4
5
6
        auto it = std::find_end(sBuf, sBuf + cSize, bytes, bytes + len);
        if(it != (sBuf + cSize))
        {
            std::rewind(file);
            return offset + std::distance(sBuf, it);
        }
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
12.04.2023, 20:57  [ТС]
DrOffset, всё работает отлично! Спасибо вам огромное за помощь!
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
12.04.2023, 21:06
blackeangel, не за что
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
25.04.2023, 08:56  [ТС]
DrOffset, здравствуйте. После долгих проб, заметил 2 вещи:
1. функция, которая ищет с конца - не находит то что находит на 0й позиции ( 0х0, то есть самый первый байт файла)
2. Функция, которая ищет все совпадения не находит последнее.
Где, что не так?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
25.04.2023, 13:03
Цитата Сообщение от blackeangel Посмотреть сообщение
функция, которая ищет с конца - не находит то что находит на 0й позиции ( 0х0, то есть самый первый байт файла)
Вместо
C++
1
    offset -= (offset - cSize != 0) ? cSize - len : cSize;
Нужно
C++
1
2
    size_t shrink = std::min(cSize - len, offset);
    offset -= shrink;
Цитата Сообщение от blackeangel Посмотреть сообщение
Функция, которая ищет все совпадения не находит последнее.
Тут не понял. Какая функция и что такое "последнее"?
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
25.04.2023, 13:43  [ТС]
DrOffset, тут пост 47 (https://www.cyberforum.ru/post16843154.html). Вашу функцию по прямому поиску сделал чтобы все найденные значения в файле складывала в вектор, а потом уже возвращала его. Но, она находит на i-1 значение. То есть самое последнее совпадение(оно же самое первое нос конца файла) не находит. Либо просто игнорирует или поиск во второй половине буфера не происходит...

Добавлено через 4 минуты
DrOffset, после замены на
C++
1
2
    size_t shrink = std::min(cSize - len, offset);
    offset -= shrink;
Ситуация не изменилась.
Вывод вот
Code
1
2
3
/data/data/ru.iiec.cxxdroid/files/iiec_tmp_binary foffset /storage/emulated/0/vbmeta.img "41574230" -1
4294967295
0xffffffff
Файл "весит" 4096 байт. Искомое значение находится в начале файла. -1 значит искать с конца файла.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.04.2023, 13:43

Функция поиска в бинарном дереве
Я понимаю как реализовать эту функцию если в бинарном дереве хранятся обычные числа(последовательно сравниваем и двигаемся по дереву в...

Создайте программу поиска вхождения строки в бинарном файле
Нужна помощь! 15. Создайте программу поиска вхождения строки в бинарном файле. Входит ли строку 'This program' в исполняемый файл...

Необычная функция в бинарном дереве поиска
Здравствуйте, уважаемые форумчане. Очень прошу Вашей помощи. Задание: Реализовать структуру данных двоичное дерево поиска,...

Методика поиска аналогичного кода бинарном файле нового релиза
Здравствуйте. Попала в руки такая задача. Есть две dll. Как мне объяснили второй файл (new.dll) это новый релиз первого файла (old.dll). ...

Функция, которая меняет строку в бинарном файле
Есть бинарный файл с информацией про олимпийские игры. И должна быть функция, изменения этой информации по желанию пользователя. все...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Клиент
Uhbif79 18.06.2026
Здесь простой клиент для работы с сервером.
Сервер
Uhbif79 18.06.2026
Выкладываю простейший сервер.
Дефенестрация
kumehtar 18.06.2026
Узнал интересное слово. Дефенестрация. Это когда ты выбрасываешь кого-либо или что-либо из окна. Возьму на вооружение)))
Дихотомия добра и зла
kumehtar 18.06.2026
Как Дзен-буддисты говорят о добре и зле: не нужно воевать против зла, нужно воевать против невежества. Тогда добро станет ествественным, и поэтому вечным. Но дело в том, что невежество всё время. . .
Своя Интернет-Компания
iceja 18.06.2026
Я программист с экономическим образованием, пишу свой проект, это SaaS для бизнесов. Мне нужен co-founder с высшим экономическим образованием, и/ или инвестор. Сейчас проект в интенсивной разработке,. . .
24 Мат модель здравосохранения: функциональные требования к строительству пищеблока
anaschu 18.06.2026
СРесурсами1: финансовый SD-контур, калькулятор функциональных требований пищеблока Сегодня разделили затраты в агенте Экономика по образцу модели НАСОСЫ, добавили расчёт ROI и построили первый. . .
23. что сделано за последнее время.
anaschu 17.06.2026
• Эталон: Клиника НИИ питания РАМН, Москва — централизованный пищеблок, 225 коек, 180 пациентов • Git: репозиторий med2, ветка абсентеизм. Рабочий файл: СРесурсами1_v4. alp • Смежный проект:. . .
22. Подключение слоя системной динамики (потоковые диффуры): экономические метрики модели
anaschu 17.06.2026
Апдейт модели: финансовый контур, разделение затрат Продолжаю развивать модель рабочего коллектива на AnyLogic. В этот раз работа шла над агентом Экономика — финансовым SD-слоем модели. Задача:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru