Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Поиск в бинарном файле 
:(
    Опции темы
TheDestroyer
Дата 25.7.2009, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Здравствуйте, необходимо искать в бинарном файле заданную последовательность байт и запоминать позицию (адрес) для последующей записи в найденное место.
Есть пример из MSDN:
Код

#include <stdio.h>
int main( void )
{
   FILE *stream;
   char line[81];
   int  result;
   if ( fopen_s( &stream, "file.exe", "w" ) != 0 )
   {
      printf( "The file was not opened\n" );
      return -1;
   }
   fprintf( stream, "The fseek begins here: "
                    "This is the file 'fseek.out'.\n" );
   result = fseek( stream, 23L, SEEK_SET);
   if( result )
      perror( "Fseek failed" );
   else
   {
      fgets( line, 80, stream );
      printf( "%s", line );
    }
   fclose( stream );
}

Но fseek ставит указатель на заданный адрес, а мне надо найти последовательность байт. 
Неужели надо использовать fread() в цикле, чтобы пройти по всему файлу? Может есть специальная функция для этого? 
Код

 int numread;
 char list[30];
 numread = fread( list, sizeof( char ), 25, stream );

Использовать getline() для поиска байтов тут вроде неправильно, т.к. она для текста.
Подскажите пожалуйста как правильно найти последовательность байт в бинарном файле и запомнить адрес для последующей записи?
PM MAIL   Вверх
jonie
Дата 25.7.2009, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



вы использете текстовый режим (он по умолчанию) открытия файла:
Код

if ( fopen_s( &stream, "file.exe", "w" ) != 0 )
используйте бинарный ("wb")


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
TheDestroyer
Дата 25.7.2009, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Спасибо за подсказку, но вопрос остается - как лучше искать заданную последовательность байт в бинарном файле чтобы запомнить адрес для последующей записи?
PM MAIL   Вверх
GoldFinch
Дата 25.7.2009, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



TheDestroyer, если файл размеров в единицы-десятки мегобайт, считай его в память, и ищи в памяти
PM MAIL ICQ   Вверх
andrew_121
Дата 25.7.2009, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



TheDestroyer, Что именно нужно найти в файле? Опишите...


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
TheDestroyer
Дата 25.7.2009, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Описываю:
Есть exe фаилы. Необходимо найти в каждом заданную последовательность байт (метку), прочитать начиная с адреса этой метки заданное число байт и прочитав, записать на это место другие заданные байты.
Пока никак не могу понять - как искать именно последовательность байт, может так:
Код

#include <stdio.h>
int main( void )
{
FILE *stream;
char buf[1024];
unsigned char Data[] = {0xe9, 0xf2, 0x01, 0x00, 0x00};
int  result;
int b_to_read_count = 1024;
if ( fopen_s( &stream, "file.exe", "wb" ) != 0 )
{
  printf( "The file was not opened\n" );
  return -1;
}
while (!eof) // <==?
{
numread = fread(buf, sizeof( char ), b_to_read_count, stream ); // читаем по 1кб
// поиск в buf заданной последовательности <==?
}
fclose( stream );
}

Проблемы:
1. Как читать с условием, что еще не конец файла? (аргумент while())
2. Поиск должен быть непростым поиском совпадения в считанном массиве, т.к. искомая комбинация байт может быть 0x01 0x02 0x03, а считываение может попасть только на часть этой последовательности, в итоге ничего найдено не будет.
Наверняка есть стандартный способ для этой задачи.
PM MAIL   Вверх
andrew_121
Дата 25.7.2009, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



Цитата(TheDestroyer @  25.7.2009,  22:19 Найти цитируемый пост)
1. Как читать с условием, что еще не конец файла? (аргумент while())

Код

while ( !feof(stream) ) {
...
}


Цитата(TheDestroyer @  25.7.2009,  22:19 Найти цитируемый пост)
2. Поиск должен быть непростым поиском совпадения в считанном массиве

Используй отображение в память.
http://msdn.microsoft.com/en-us/library/aa...28VS.85%29.aspx << тут есть пример
http://www.developing.ru/com/memory_mapped_files_01.html

Добавлено через 2 минуты и 19 секунд
Т.е. В это случае логичнее использовать отображение файла в память. И все операции становятся аналогичными работе с массивом. И изменять его тоже можно.

Добавлено через 12 минут и 9 секунд
вот еще пример: http://rghost.ru/366127
сюда выгружаться не хочет почему-то...


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
vnsk
Дата 26.7.2009, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 22.7.2009

Репутация: нет
Всего: нет



Вариант на С:
Код
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main( void )
{
    FILE *stream;
    unsigned char *buf, *str;
    unsigned char Data[] = {0xe9, 0xf2, 0x01, 0x00, 0x00};
    int  result;
    unsigned int  f_size;
    
    if( (stream = fopen("file.exe", "wb")) != 0 ) {
        printf( "The file was not opened\n" );
        return -1;
    }
    f_size = fseek( stream, 0, SEEK_END );   // рамер файла
    if( (buf = (unsigned char*)malloc(f_size + 1)) == NULL )  //  +1 - для образования строки данных
        return -2;
    if(  fread(buf, sizeof( char ), f_size, stream) != f_size ) {  // читаем все и сразу
        free( buf );
        return -3;
    }
    buf[f_size] = (unsigned char)0;  
    
    result = 0;   // ко-во включений
    str = buf;    // "подобрали ногу"  :)
    // поиск подстроки (Data) в строке (str); возвращается адрес первой подстроки, иначе - NULL
    while ( (str = (unsigned char*)strstr((const char*)str, (const char*)Data)) != NULL )  
        result++;
    
    free( buf );
    fclose( stream );
    return  0;   // ok
}

P.S.  Предполагается, что в файле нет нулевых символов. В противном случае необходимо написать  собственную функцию - аналог strstr() - нахождения построки  УЖЕ не в строке, а в массиве данных.


Модератор: Не забываем пользоваться кнопочкой "Код"

Это сообщение отредактировал(а) bsa - 27.7.2009, 10:59
PM MAIL   Вверх
andrew_121
Дата 26.7.2009, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



Цитата(vnsk @  26.7.2009,  13:30 Найти цитируемый пост)
    f_size = fseek( stream, 0, SEEK_END );   // рамер файла

После этой строки нужно добавить:
Код

fseek(stream, 0L, SEEK_SET);



Цитата(vnsk @  26.7.2009,  13:30 Найти цитируемый пост)
    // поиск подстроки (Data) в строке (str); возвращается адрес первой подстроки, иначе - NULL
    while ( (str = (unsigned char*)strstr((const char*)str, (const char*)Data)) != NULL )  

Судя по этому:
Цитата(TheDestroyer @  25.7.2009,  22:19 Найти цитируемый пост)
unsigned char Data[] = {0xe9, 0xf2, 0x01, 0x00, 0x00};

искать нужно не строку.


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
vnsk
Дата 26.7.2009, 17:05 (ссылка)   | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 22.7.2009

Репутация: нет
Всего: нет



> После этой строки нужно добавить:
> fseek(stream, 0L, SEEK_SET);
Да. Обязательною

 > Судя по этому:
> unsigned char Data[] = {0xe9, 0xf2, 0x01, 0x00, 0x00}; 
> искать нужно не строку. 
А что больше смущает? - Написание конретной требуемой функции или сенарий "что делать"?

Вариант на "С":
Код
int DataInMem( char *data, char *mem,  int n_max )
{
  int  ii=0, jj,  len;
  len = strlen(data);  // data[] у нас строка  
  do {
     if( data[0] == mem[ii] ) {
        for( jj=0; jj<len; jj++  ) {
           if( data[jj] != mem[ii+jj] )   
              break; 
       }
       if( jj == len )
         return   ii;   // начальный индекс в массиве для первого вхождения подстроки
       else
         ii += jj;      // сдвигаем индекс на величину просмотренных байтов
    }
  } while( ++ii < n_max-len );  //  смотрим до места, когда в конце массива еще может быть подстрока
  return  -1;  // нет подстроки
}



Модератор: Не забываем пользоваться кнопочкой "Код"

Это сообщение отредактировал(а) bsa - 27.7.2009, 11:00
PM MAIL   Вверх
zim22
Дата 26.7.2009, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



 smile 
vnsk, я вас прошу,
во-первых, комментируйте с помощью тегов QUOTE, а не 
Цитата(vnsk @  26.7.2009,  17:05 Найти цитируемый пост)

> После этой строки нужно добавить:
> fseek(stream, 0L, SEEK_SET);

во-вторых, исходники оформляйте с помощью тега CODE
***
Цитата(vnsk @  26.7.2009,  17:05 Найти цитируемый пост)
  len = strlen(data);  // data[] у нас строка  

strlen до нулевого символа считает. она не подходит здесь, т.к. элементы массива могут иметь любые значения.
Код

unsigned char Data[] = {0xe9, 0x00, 0xff, 0x00, 0x00};

размер массива определяется так:
Код

int size = sizeof(Data) / sizeof(*Data);



Это сообщение отредактировал(а) zim22 - 26.7.2009, 18:07


--------------------
PM MAIL   Вверх
andrew_121
Дата 26.7.2009, 19:01 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



vnsk, Пожалуй....Зим22 все сказал.

Это сообщение отредактировал(а) andrew_121 - 26.7.2009, 19:01


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
jonie
Дата 27.7.2009, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Цитата
размер массива определяется так:

если не ошибаюсь что есть готовый макрос: _countof(X), каждый рыз sizeof-ы городить утомительно...


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
ЗапаснойЛеопольд
Дата 27.7.2009, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 29.6.2009

Репутация: нет
Всего: нет



Цитата(zim22 @ 26.7.2009,  17:16)
Код

unsigned char Data[] = {0xe9, 0x00, 0xff, 0x00, 0x00};

размер массива определяется так:
Код

int size = sizeof(Data) / sizeof(*Data);

Это было бы справедливо если sizeof применять к массиву, а не к указателю на char, как у него. 
int DataInMem( char *data, char *mem,  int n_max )

Надо бы вычислять длинну вне функции, и передавать её отдельным аргументом.


Это сообщение отредактировал(а) ЗапаснойЛеопольд - 27.7.2009, 11:20
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0914 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.