2009-11-17 8 views
0

J'essaye d'écrire un petit programme qui va chercher un fichier binaire pour quelques octets et les remplacer par un autre paquet d'octets. Mais chaque fois que j'essaie d'exécuter cette petite application, j'ai reçu un message à propos de istream_iterator n'est pas dereferenceable. Peut-être que quelqu'un a une suggestion sur la façon de le faire d'une autre manière (les itérateurs sont un peu un nouveau sujet pour moi).Modification de fichiers binaires

#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; 
} 

Ceci est ma deuxième tentative de le faire, mais aussi quelque chose ne va pas. Avec de petits fichiers, ça a l'air de fonctionner correctement mais avec un gros (environ 2 Mo) ça marche très lentement et ne trouve jamais de motif ce que je cherche.

#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; 
} 

Cheers, Thomas

Répondre

1

Lire une plus grande partie du fichier à la mémoire, le remplacer dans la mémoire, puis vider la grappe sur le disque. La lecture d'un octet à la fois est très lente.

Je vous suggère également de lire à propos de mmap (ou MapViewOfFile dans win32).

0

search ne fonctionnera pas sur un istream_iterator en raison de la nature de l'itérateur. C'est un itérateur d'entrée, ce qui signifie qu'il se déplace simplement vers l'avant - c'est parce qu'il lit à partir du flux, et une fois qu'il est lu dans le flux, il ne peut pas revenir en arrière. search nécessite un itérateur avant, qui est un itérateur d'entrée dans lequel vous pouvez vous arrêter, faire une copie et en déplacer une vers l'avant tout en conservant l'ancien. Un exemple d'un itérateur avant est une liste à liaison unique. Vous ne pouvez pas revenir en arrière, mais vous pouvez vous rappeler où vous êtes et recommencer à partir de là.

Le problème de vitesse est parce que le vecteur est vraiment terrible à manipuler des données inconnues. Chaque fois qu'il manque de place, il copie tout le tampon dans une nouvelle mémoire. Remplacez-le par un deque, qui peut gérer les données arrivant une par une. Vous obtiendrez également des performances améliorées en essayant de lire le flux en blocs à la fois, car l'accès caractère par caractère est une très mauvaise façon de charger un fichier entier en mémoire.

0

En supposant que le fichier n'est pas trop volumineux, il suffit de lire le fichier en mémoire, puis de modifier le tampon mémoire comme bon vous semble, puis de le réécrire dans un fichier.

E.g. (non testé):

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); 
Questions connexes