Reading binary file created a C++ program inside a Perl prog

F

freesoft12

Hi,

I have a written a C++ program that writes a set of paths into a
binary file. In the program, the 'write_binary()', writes to the
binary file and the 'read_binary()' opens the binary file, reads the
data and prints it out.

Here is the C++ program:
-----------------------------
#include <vector>
#include <string>
#include <stdio.h>

using namespace std;

void
write_binary()
{
vector<string> v;
v.push_back("/a/b/c/d");
v.push_back("/e/f");
v.push_back("../h");

FILE *fp = fopen("rw_binary.dat","w");
if (!fp)
{
printf("Error: Unable to open ./rw_binary.dat\n");
exit(1);
}

for (vector<string>::const_iterator
it(v.begin()),itEnd(v.end());it!=itEnd;++it)
{
unsigned size = it->size()+1;
fwrite(&size,sizeof(unsigned),1,fp);
fwrite(it->c_str(),sizeof(char),size,fp);
}
fclose(fp);
}

void
read_binary()
{
FILE *fp = fopen("rw_binary.dat","r");
while (!feof(fp))
{
unsigned size(0);
fread(&size,sizeof(unsigned),1,fp);
char *buf = (char*)malloc(size*sizeof(char));
fread(buf,sizeof(char),size,fp);
printf("%s\n",buf);
free(buf);
}
fclose(fp);
}

int main()
{
write_binary();

read_binary();

return 0;
}
----------------------


I wanted to create a Perl program that mimics the 'read_binary()'. But
I am getting a perl warning ( I have the 'use strict & diagnostics').

Here it is:

-----------------------
eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec
perl -w -S $0 $argv:q' if 0;
#

use strict;
use diagnostics;

open(IN,"/home/rradhakr/progs/rw_binary.dat") or die "Cannot open
rw_binary.dat\n";
binmode(IN);
while (<IN>) {
my $buf = 0;
read(IN,$buf,6);
my $string = undef;
read(IN,$string,$size);
print "$size\n";
}
close(IN);
-------------------------

Here is the error I get Perl:

Argument "" isn't numeric in read at read_binary_file.pl line 13, <IN>
line 1 (#1)
(W numeric) The indicated string was fed as an argument to an
operator that expected a numeric value instead. If you're fortunate
the message will identify which operator was so unfortunate.

Any suggestions?

Regards
John
 
P

Peter J. Holzer

unsigned size = it->size()+1;
fwrite(&size,sizeof(unsigned),1,fp);

So this writes sizeof(unsigned) bytes containing the (implementation
defined) binary representation of an unsigned int. You will need to
check your compiler documentation for the details and be aware that they
can change when you use a different compiler (or the same compiler using
different flags).

fwrite(it->c_str(),sizeof(char),size,fp);

This writes the string including the terminating "\0".
while (<IN>) {

Here you read one line (i.e. everything up to including the first "\n"
byte). Why?
my $buf = 0;
read(IN,$buf,6);
^
Where does the number 6 come from?
You are obviously trying to read the unsigned int written by the C++
compiler. While it is theoretically possible that your unsigned ints are
6 bytes long, that would be extremely unusual. Most likely they are 4
bytes long (but 2 or 8 are also possible).

my $string = undef;
read(IN,$string,$size);

Where does $size come from? You read the size into $buf, not into $size.
Plus, the $buf will contain the size in the format specific to your C++
compiler, so you need to unpack() (see perldoc -f unpack) it before you
can use it.

print "$size\n";

Why do you print $size instead of the $string?
}
close(IN);

hp
 
P

Peter J. Holzer

I wanted to create a Perl program that mimics the 'read_binary()'. But
I am getting a perl warning ( I have the 'use strict & diagnostics').

Here it is:

-----------------------
eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec
perl -w -S $0 $argv:q' if 0;
#

use strict;
use diagnostics;

open(IN,"/home/rradhakr/progs/rw_binary.dat") or die "Cannot open
rw_binary.dat\n";
binmode(IN);
while (<IN>) {
my $buf = 0;
read(IN,$buf,6);
my $string = undef;
read(IN,$string,$size);
print "$size\n";
}
close(IN);
-------------------------

Here is the error I get Perl:

Argument "" isn't numeric in read at read_binary_file.pl line 13, <IN>
line 1 (#1)

Just noticed this now. This is impossible. Your program cannot even
start since you forgot to declare $size.

You were obviously running a different program than the one you posted.
Please don't do that.

hp
 
P

Peter Makholm

I wanted to create a Perl program that mimics the 'read_binary()'. But
I am getting a perl warning ( I have the 'use strict & diagnostics').

Are you sure that you pasted the right code? Neither $string nor $size
is declared and I'm sure that 'use strict' would complain about this
before the erroryou have pasted?
-----------------------
eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec
perl -w -S $0 $argv:q' if 0;
#

use strict;
use diagnostics;

open(IN,"/home/rradhakr/progs/rw_binary.dat") or die "Cannot open
rw_binary.dat\n";

A matter of style, but use a lexical filehandle and the three-argument
form of open. Incluing $! in the error message will also be usefull
some time in the future:

open my $fh, '<', '/home/rradhakr/progs/rw_binary.dat'
or die "Couldn't open rw_binary.dat: $!";

As a consequence all occurences of IN should be replaced by $fh.
binmode(IN);
while (<IN>) {

Here you read one line from the file including the line separator ("\n").
my $buf = 0;

Why? $buf is unconditionally overwritten by the next statement
read(IN,$buf,6);

Here you read the following 6 bytes into $buf.
my $string = undef;

This "initialization" is even worse. You never have to do an explicite
initialization to undef. And then again, $string will be
unconditionally overwritten by the following read.
read(IN,$string,$size);

Here you read the following $size bytes into $string. BUT you havn't
showed us where $size is declared, much less where it gets it's value
from. If you code uses 'use strict' you clearly havn't pasted you
complete code.

But my guess is that this is line 13 and you somehow never initializes
$size with an correct value.
print "$size\n";
}
close(IN);

Mixing reading files with the <> operator and with read() is confusing
at best (and at least calls for a comment in you code) and plain wrong
most of time. My guess is that your case is the latter

//Makholm
 
F

freesoft12

Sorry about that, I posted the Perl program that I was playing with.
Here is the orig Perl program:

while (<IN>) {
my $size = 0;
read(IN,$size,1);
my $string = undef;
read(IN,$string,$size);
print "$string\n";
}
close(IN);
 
S

sln

Hi,

I have a written a C++ program that writes a set of paths into a
binary file. In the program, the 'write_binary()', writes to the
binary file and the 'read_binary()' opens the binary file, reads the
data and prints it out.
[your code snipped]

It looks like you are dealing with strings and is a simple case of
writing the length and string combo's.

If thats all your doing, the solution is to mitigate machine dependencies.
There's really no need to travel down the *binary* highway unless you have to.
The Perl itself couldn't be simpler, its almost a one liner.

-sln

-----------------------------

// JBin.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>

using namespace std;

void write_binary();
void read_binary();

int _tmain(int argc, _TCHAR* argv[])
{
write_binary();
read_binary();
system("perl ../jbin.pl");
return 0;
}

//
void write_binary()
{
vector<string> v;
v.push_back( "/a/b/c/d");
v.push_back( "/e/f");
v.push_back( "../h");

FILE *fp = fopen( "rw_binary.dat", "w"); // wb ??
if (!fp)
{
printf( "Error: Unable to open ./rw_binary.dat for write\n");
exit(1);
}
char buf[100];
for( vector<string>::const_iterator it(v.begin()),itEnd(v.end()); it!=itEnd; it++)
{
strcat( itoa( it->size(), buf, 10), "\n");
fputs( buf, fp);
fputs( it->c_str(), fp);
}
fclose(fp);
}

//
void read_binary()
{
FILE *fp = fopen( "rw_binary.dat", "r"); // rb ??
if (!fp)
{
printf( "Error: Unable to open ./rw_binary.dat for read\n");
exit(1);
}
printf( "\nFrom C++ ...\n");
char buf[100];
while (!feof(fp) && fgets( buf, 100, fp))
{
size_t count = atoi( buf);
char *sdata = (char *)malloc( count+1);
memset( sdata, 0, count+1);
fread( sdata, count, 1, fp);
printf( "'%s'\n", sdata);
free( sdata);
}
fclose(fp);
}

/*
# Jbin.pl
use strict;
use warnings;

open (my $fh, '<', 'rw_binary.dat') or die "Cannot open 'rw_binary.dat' for read: $!";
print "\nFrom perl ...\n";

my $buf;
while (<$fh>) {
read ($fh, $buf, $_);
print "'$buf'\n";
}
close($fh);
__END__
*/

/* Console output:

From C++ ...
'/a/b/c/d'
'/e/f'
'../h'

From perl ...
'/a/b/c/d'
'/e/f'
'../h'
Press any key to continue . . .
*/
 

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,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top