#include a binary file?

G

Gary

Hi all,

I have a situation where I need to generate a new binary file which
just changes a couple of bytes in a couple of places in a pre-existing
master template file.

I can open and read the original file byte by byte and spew it out to
a new file, just changing the appropriate bytes. However since these
files are only about 1k bytes long, I'd like to include those bytes
directly into my code, e.g. as a static array. This would create a
cleaner situation in that I wouldn't have to know where the original
file was, worry about it getting deleted/moved/modified etc. And the
code generation would be a little easier (not that it is hard).

However I am unclear how you would go about attaching a label to the
top of it, making sure that the compiler didn't rearrange any bytes,
and of course, how to make the compiler treat this as just a block of
literal bytes to be considered static data rather than inline assembly
or whatever.

Let's say the file contains 4 bytes, FF FD 45 34

I want something that creates the equivalent of:

char template_file[] = {0xFF, 0xFD, 0X45, 0x34 };

I am using Visual C++ version 6.

Thanks for any hints.
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Gary escribió:
Let's say the file contains 4 bytes, FF FD 45 34

I want something that creates the equivalent of:

char template_file[] = {0xFF, 0xFD, 0X45, 0x34 };

Why the equivalent? Create just that.

Regards.
 
E

Erik

Hi all,
I have a situation where I need to generate a new binary file which
just changes a couple of bytes in a couple of places in a pre-existing
master template file.

I can open and read the original file byte by byte and spew it out to
a new file, just changing the appropriate bytes. However since these
files are only about 1k bytes long, I'd like to include those bytes
directly into my code, e.g. as a static array. This would create a
cleaner situation in that I wouldn't have to know where the original
file was, worry about it getting deleted/moved/modified etc. And the
code generation would be a little easier (not that it is hard).

However I am unclear how you would go about attaching a label to the
top of it, making sure that the compiler didn't rearrange any bytes,
and of course, how to make the compiler treat this as just a block of
literal bytes to be considered static data rather than inline assembly
or whatever.

Let's say the file contains 4 bytes, FF FD 45 34

I want something that creates the equivalent of:

char template_file[] = {0xFF, 0xFD, 0X45, 0x34 };

I am using Visual C++ version 6.

When I had this problem, I solved it by adding an assembly module that I
used Nasm to assemble
(it has a directive called incbin or something like that).
The output file can then be linked with the Visual C++ object files.
You can get nasm from http://sourceforge.net/projects/nasm.

/ Erik
 
G

Gregg

Gary said:
Hi all,

[...]

Let's say the file contains 4 bytes, FF FD 45 34

I want something that creates the equivalent of:

char template_file[] = {0xFF, 0xFD, 0X45, 0x34 };

I am using Visual C++ version 6.

Thanks for any hints.

Just write a simple utility that reads the binary file and generates a .cpp
file with the above definition in it, and then link with or include this in
your program. You can run the program as a pre-build step, ore maybe create
a build dependency so it is not run unnecessarily.
 
K

Kevin Goodsell

Gary said:
Julián Albo said:
Gary escribi :

Let's say the file contains 4 bytes, FF FD 45 34
I want something that creates the equivalent of:
char template file[] = {0xFF, 0xFD, 0X45, 0x34 };

Why the equivalent? Create just that.

Because the file is actually 1000 bytes long?

I like Gregg's solution. An alternative would be something like this:

char template_file[] = {

#include "bytes.dat"

};

But the file has to be in the expected format. Therefore, if it's just a
binary file you'll have to convert it first. Basically you end up with a
less elegant version of Gregg's solution, but it's possible that it
could be better suited to your particular problem.

-Kevin
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Gary escribió:
Let's say the file contains 4 bytes, FF FD 45 34
I want something that creates the equivalent of:
char template file[] = {0xFF, 0xFD, 0X45, 0x34 };
Why the equivalent? Create just that.
Because the file is actually 1000 bytes long?

Can't you write a program that do the conversion for you?

Regards.
 
K

Karl Heinz Buchegger

Gary said:
Julián Albo said:
Gary escribi :
Let's say the file contains 4 bytes, FF FD 45 34
I want something that creates the equivalent of:
char template file[] = {0xFF, 0xFD, 0X45, 0x34 };

Why the equivalent? Create just that.

Regards.

Because the file is actually 1000 bytes long?

A perfect task for a program to do it.
You are a programmer, aren't you?
 
G

Gary

Karl Heinz Buchegger said:
A perfect task for a program to do it.
You are a programmer, aren't you?

Hmmmm.... I write file-conversion programs to suit very specific needs
I have for transferring data between various audio programs on the
order of once every three years. So I don't really consider myself a
"programmer". I am just trying to get over this particular hump at
which point I may never write another program, unless the need arises.

I certainly don't get *paid* to do it. Between 20 and 10 years ago I
did get paid to write C and assembler for embedded systems. I taught
myself Windows API (pre-MFC) and C++ by reading books and using the
compilers but never had a job doing this, nor did I study programming
in college beyond mandatory BASIC (gasp) FORTRAN (erkk) and assembler
(SHL A). Still I find myself most comfortable writing console type
apps in C... but can just barely manage to do Windows apps using MFC
in C++. If I hadn't found the code to an MFC program I wrote 3 years
ago I would be writing a console app!

Anyway I thought this NG would be a good place to ask, and I got the
answer I needed. C++ has so many things that I'm not familiar with
that I thought this might be one of them. A program to read a binary
file and print each byte followed by a comma will be trivial and I am
not even going to worry about trimming the last comma. I'll just do
it by hand!

Thanks to all for the helpful responses.
 
G

Gregg

[...]
that I thought this might be one of them. A program to read a binary
file and print each byte followed by a comma will be trivial and I am
not even going to worry about trimming the last comma. I'll just do
it by hand!

You don't have to. It is valid to leave the trailing comma. E.g.,

char data[] = { 1, 2, 3, };

is valid.
 
G

Gary

Gregg said:
You don't have to. It is valid to leave the trailing comma. E.g.,

char data[] = { 1, 2, 3, };

Yeah, but it's kinda like a "dangling chad" to me. Just personal preference.
 
G

Gary

OK, at the risk of drawing ire, here's my "C" code entry in solution
of this problem. Can it be made more straightforward in C++?

#include "stdio.h"

int main(int argc, char **argv)
{
char c;
FILE *binfile;
int ii,i;

if(argc != 2)
return(-1);

binfile = fopen(argv[1], "rb");

if(binfile != NULL)
{
printf("char %s[] = \n{\n",argv[1]);
i = 0;
while(!feof(binfile))
{
if((i % 88) == 0)
{
printf("\n/* ");
for(ii = 0; ii < 8; ii++)
printf("[%4x]",i + ii);
printf("*/");
}
if((i % 8) == 0)
printf("\n/*[%4x]*/ ",i);
i++;
c = getc(binfile);
printf("0x%2.2x, ", c & 0xff);
}
printf("\n};\n");
return i;
}
else
return 0;
}
 
K

Karl Heinz Buchegger

Gary said:
OK, at the risk of drawing ire, here's my "C" code entry in solution
of this problem. Can it be made more straightforward in C++?

Well. At least it can be made correct in C :)

feof returns true only until you have tried AND failed to read past
the end of file.

Thus whenever you see a loop:

while( !feof( ... ) {

// read from file
// do something with the thing read
}

you know immediatly that this will not work correctly
in all circumstances (usually the last thing read from the file
will be processed twice)

feof is meant to be used *after* the reading loop has terminated
to figure out *why* the loop has termineted. If it was because of
eof, then everything is correct, the file has been read completely.

Note that getc (as well as fgetc) returns an int and not a char!!!! This is
important because getc and fgetc need a way to tell the caller: EOF reached
or some other error condition, stop reading from the file.

The following uses this. It is based on what you had:

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] )
{
int Byte;
FILE* BinFile;
int ii,i;

if( argc != 2 )
{
printf( "Usage: DumpBin <FileName>\n" );
return EXIT_FAILURE;
}

BinFile = fopen( argv[1], "rb" );

if( !BinFile )
{
printf( "Error: Failed to open file: '%s'\n", argv[1] );
return EXIT_FAILURE;
}

printf( "char %s[] = \n{\n", argv[1] );
i = 0;

while( ( Byte = fgetc( BinFile ) ) != EOF )
{
if( (i % 88) == 0 )
{
printf("\n/* ");
for(ii = 0; ii < 8; ii++)
printf("[%04x]",i + ii);
printf("*/");
}
if((i % 8) == 0)
printf("\n/*[%04x]*/ ",i);
i++;

printf( "0x%02x, ", Byte );
}

if( !feof( BinFile ) )
{
printf( "Error: Reding from file: '%s'\n", argv[1] );
printf( " Could read %d bytes before failure\n", i );
fclose( BinFile );
return EXIT_FAILURE;
}

printf("\n};\n");
fclose( BinFile );

return EXIT_SUCCESS;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,815
Messages
2,569,705
Members
45,494
Latest member
KandyFrank

Latest Threads

Top