修改二进制文件

时间:2009-11-17 21:28:35

标签: c++ visual-c++

我正在尝试编写一个小程序,它将搜索二进制文件中的几个字节,并用另一堆字节替换它们。但每当我尝试运行这个小应用程序时,我收到的消息是 istream_iterator不能解除引用 。 也许有人建议如何以另一种方式做到这一点(迭代器对我来说有点像新主题)。

#include <fstream>
#include <iterator>
#include <algorithm>

using namespace std;

int main() {

typedef istream_iterator<char> input_iter_t;

const off_t SIZE = 4;
char before[SIZE] = { 0x12, 0x34, 0x56, 0x78 };
char  after[SIZE] = { 0x78, 0x12, 0x34, 0x65 };

fstream filestream("numbers.exe", ios::binary | ios::in | ios::out);

if (search(input_iter_t(filestream), input_iter_t(), before, before + SIZE) != input_iter_t()) {
    filestream.seekp(-SIZE, ios::cur);
    filestream.write(after, SIZE);
}

return 0;
}

这是我第二次尝试这样做,但也有问题。小文件似乎工作正常,但更大(大约2MB)它工作得非常慢,从来没有找到我正在寻找的模式。

#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <windows.h>

using namespace std;

int main() {

const off_t Size = 4;
unsigned char before[Size] = { 0x12, 0x34, 0x56, 0x78 };
unsigned char  after[Size] = { 0x90, 0xAB, 0xCD, 0xEF };

    vector<char> bytes;
    {
        ifstream iFilestream( "numbers.exe", ios::in|ios::binary );
        istream_iterator<char> begin(iFilestream), end;
        bytes.assign( begin, end ) ;
    }

    vector<char>::iterator found = search( bytes.begin(), bytes.end(), before, before + Size );
    if( found != bytes.end() )
    {
        copy( after, after + Size, found );
        {
            ofstream oFilestream( "number-modified.exe" );
            copy( bytes.begin(), bytes.end(), ostream_iterator<unsigned char>(oFilestream) );
        }
    }
return 0;
}

干杯, 托马斯

3 个答案:

答案 0 :(得分:1)

将大部分文件读入内存,将其替换为内存,然后将该堆转储到磁盘。一次读取一个字节非常慢。

我还建议您阅读有关mmap(或win32中的MapViewOfFile)的内容。

答案 1 :(得分:0)

由于迭代器的性质,

search无法在istream_iterator上运行。它是一个输入迭代器,这意味着它只是向前移动 - 这是因为它从流中读取,一旦从流中读取,它就无法返回。 search需要一个前向迭代器,它是一个输入迭代器,您可以在此处停止,复制并向前移动一个,同时保留旧的迭代器。前向迭代器的一个例子是单链表。你不能倒退,但你可以记住你在哪里并从那里重新开始。

速度问题是因为矢量在处理未知数据时非常糟糕。每次空间不足时,它会将整个缓冲区复制到新内存中。将其替换为deque,它可以处理逐个到达的数据。尝试一次读取块中的流也可能会提高性能,因为逐个字符的访问是将整个文件加载到内存中的一种非常糟糕的方式。

答案 2 :(得分:0)

假设文件不是太大,只需将文件读入内存,然后根据需要修改内存缓冲区,然后将其写回文件。

E.g。 (另):

FILE *f_in = fopen("inputfile","rb");
fseek(f_in,0,SEEK_END);

long size = ftell(f_in);
rewind(f_in);

char* p_buffer = (char*) malloc (size);
fread (p_buffer,size,1,f_in);
fclose(f_in);

unsigned char *p= (unsigned char*)p_buffer;

// process.

FILE *f_out = fopen("outoutfile","wb");
fwrite(p_buffer,size,1,f_out);
fclose(f_out);

free(p_buffer);