From: freesoft12 on
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
From: Peter J. Holzer on
On 2010-02-09 19:16, freesoft12(a)gmail.com <freesoft12(a)gmail.com> wrote:
> 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

From: Peter J. Holzer on
On 2010-02-09 19:16, freesoft12(a)gmail.com <freesoft12(a)gmail.com> wrote:
> 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
From: Peter Makholm on
"freesoft12(a)gmail.com" <freesoft12(a)gmail.com> writes:

> 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
From: freesoft12 on
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);