Re: find a pattern in binary file
James Kanze wrote:
On Jun 21, 2:13 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
Ivan wrote:
On Jun 20, 1:11 pm, vizzz <andrea.visin...@gmail.com> wrote:
Hmmm... I had a look at this and ran accross a simple
problem. How do you read a binary file and just echo the
HEX for byte to the screen.
#include <iostream>
#include <ostream>
#include <fstream>
#include <iterator>
#include <iomanip>
#include <algorithm>
#include <cassert>
class print_hex {
std::ostream * ostr_ptr;
unsigned int line_length;
unsigned int index;
public:
print_hex ( std::ostream & str_ref, unsigned int length )
: ostr_ptr( &str_ref )
, line_length ( length )
, index ( 0 )
{}
void operator() ( unsigned char ch ) {
++index;
if ( index >= line_length ) {
(*ostr_ptr) << std::hex << std::setw(2) << std::setfill( '0' )
<< (unsigned int)(ch) << '\n';
index = 0;
} else {
(*ostr_ptr) << std::hex << std::setw(2) << std::setfill( '0' )
<< (unsigned int)(ch) << ' ';
Wouldn't it be preferable to set the formatting flags in the
constructor?
Yup.
I'd also provide an "indent" argument; if index
were 0, I'd output indent spaces, otherwise a single space---or
perhaps the best solution would be to provide a start of line
and a separator string to the constructor, then:
Good idea.
(*ostr_ptr)
<< (inLineCount == 0 ? startString : separString)
<< std::setw( 2 ) << (unsigned int)( ch ) ;
++ inLineCount ;
if ( inLineCount == lineLength ) {
(*ostr_ptr) << endString ;
inLineCount = 0 ;
}
(This supposes that hex and fill were set in the constructor.)
Given the copying that's going on, I'd also simulate move
semantics, so that the final destructor could do something like:
if ( inLineCount != 0 ) {
(*ostr_ptr) << endString ;
}
}
}
};
int main ( int argn, char ** args ) {
assert( argn == 2 );
std::ifstream in ( args[1] );
std::for_each( std::istreambuf_iterator< char >( in ),
std::istreambuf_iterator< char >(),
print_hex( std::cout, 25 ) );
Unless you're doing something relatively generic, with support
for different separators, etc., this really looks like a case of
for_each abuse.
Actually, with regard to for_each, I am growing more and more comfortable
using it. Of all algorithms, for_each seems the most silly; on the other
hand it is also the one that has the largest potential for specialized
versions that take advantage of internal knowledge about the underlying
sequence. E.g., I can easily imagine a special version for iterators into a
deque (where for_each would iterate over pages and within each page would
use a very fast loop using T* where it can skip the test for reaching a
page end). Similar optimizations should be possible for stream iterators.
std::cout << '\n';
Which results in one new line too many if the number of elements
just happened to be an exact multiple of the line length.
You are making up specs :-)
But seriously: you are right, of course.
About the only real use for this sort of output I've found is
debugging or experimenting, but there, I use it often enough
that I've a generic Dump<T> class (and a generic function which
returns it, for automatic type deduction), so that I can write
things like:
std::cout << dump( someObject ) << std::endl ;
[snip]
Hm, I never had a use for hex dumping objects. But, maybe I should try that
out.
Best
Kai-Uwe Bux