Как удалить части из двоичного файла в C ++ - PullRequest
1 голос
/ 23 июня 2011

Я хотел бы удалить детали из двоичного файла, используя C ++.Бинарный файл составляет около 5-10 МБ.

Что я хотел бы сделать:

  1. Поиск строки ANSI "что-то"
  2. После того, как я нашел эту строку, я хотел бы удалить следующие nбайтов, например следующие 1 МБ данных.Я хотел бы удалить эти символы, а не заполнять их значением NULL, чтобы уменьшить размер файла.
  3. Я хотел бы сохранить измененный файл в новый двоичный файл, который совпадает с исходным файлом,кроме отсутствующих n байтов, которые я удалил.

Можете ли вы дать мне несколько советов / рекомендаций, как сделать это наиболее эффективно? Должен ли я загрузить файл в памятьпервый?

Как я могу эффективно искать строку ANSI? Я имею в виду, возможно, мне придется пропустить несколько мегабайт данных, прежде чем я найду эту строку.>> Мне сказали, что я должен задать его в другом вопросе, поэтому он здесь: Как искать строку ANSI в двоичном файле?

Как удалитьn байт и эффективно записать его в новый файл?

ОК, мне не нужно, чтобы он был суперэффективным, файл не будет больше 10 МБ, и все будет в порядке, если он работает длянесколько секунд.

Ответы [ 3 ]

1 голос
/ 23 июня 2011

Существует ряд процедур быстрого поиска строк, которые работают намного лучше, чем тестирование каждого символа.Например, при попытке найти «что-то» нужно проверять только каждый 9-й символ.

Вот пример, который я написал для более раннего вопроса: обзор кода: поиск обратный поиск тега нанепустое окончание char str

0 голосов
/ 23 июня 2011

Во-первых, если я понимаю ваше значение в подразделе «Как я могу эффективно искать», вы не можете просто пропустить несколько мегабайт данных в поиске, если целевая строка может быть в этих первых нескольких мегабайтах.

Что касается загрузки файла в память, если вы это сделаете, не забудьте убедиться, что у вас достаточно места в памяти для всего файла.Вы будете разочарованы, если зайдете в утилиту и обнаружите, что файл объемом 2 ГБ, на котором вы хотите ее использовать, не помещается в 1,5 ГБ памяти, которую вы оставили.

Я предполагаю, что вызагрузите его в память или карту памяти для следующего.

Вы специально сказали, что это двоичный файл, так что это означает, что вы не можете использовать обычный поиск / сопоставление строк C ++ в качестве нулевых символов в данных файлабудет путать его (закончить преждевременно без спички).Вместо этого вы можете использовать memchr для поиска первого вхождения первого байта в вашей цели и memcmp для сравнения следующих нескольких байтов с байтами в цели;продолжайте использовать пары memchr / memcmp для сканирования всего объекта, пока не найдете.Это не самый эффективный способ, так как существуют более эффективные алгоритмы сопоставления с образцом, но я полагаю, что это своего рода эффективный способ.

Чтобы "удалить" n байтов, вы должны фактически переместить данные после этихn байтов, копируя всю вещь в новое место.

Если вы на самом деле копируете данные с диска в память, тогда было бы быстрее манипулировать ими и записывать в новый файл.В противном случае, как только вы найдете место на диске, с которого хотите начать удаление, вы можете открыть новый файл для записи, прочитать байты X из первого файла, где X - позиция указателя файла в первом файле, и записать их.прямо во второй файл, затем перейдите в первый файл к X + n и сделайте то же самое оттуда к файлу file1, добавив его к тому, что вы уже поместили в file2.

0 голосов
/ 23 июня 2011

Для файла размером 5-10 МБ я бы посмотрел на writev () , если ваша система поддерживает его.Прочитайте весь файл в память, так как он достаточно мал.Сканирование байтов, которые вы хотите удалить.Передайте writev () список iovecs (который будет просто указателем на ваш буфер чтения и длину), а затем вы можете переписать все измененное содержимое одним системным вызовом.

...