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

Discussion in 'Perl Misc' started by freesoft12@gmail.com, Feb 9, 2010.

  1. Guest

    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
    , Feb 9, 2010
    #1
    1. Advertising

  2. On 2010-02-09 19:16, <> 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
    Peter J. Holzer, Feb 9, 2010
    #2
    1. Advertising

  3. On 2010-02-09 19:16, <> 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
    Peter J. Holzer, Feb 9, 2010
    #3
  4. "" <> 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
    Peter Makholm, Feb 9, 2010
    #4
  5. Guest

    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);
    , Feb 10, 2010
    #5
  6. Guest

    On Tue, 9 Feb 2010 11:16:30 -0800 (PST), "" <> wrote:

    >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 . . .
    */
    , Feb 10, 2010
    #6
  7. "" <> writes:

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


    Many of the comments made by Peter J. Holzer and me still apply.

    //Makholm
    Peter Makholm, Feb 10, 2010
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nishi Bhonsle
    Replies:
    3
    Views:
    463
  2. Mei Li
    Replies:
    3
    Views:
    565
    Thomas Schodt
    Jul 20, 2004
  3. -intl.com
    Replies:
    1
    Views:
    354
    Martin Gregorie
    Oct 22, 2006
  4. Andrew Wheeler

    sending data from one program to a perl prog

    Andrew Wheeler, Apr 26, 2004, in forum: Perl Misc
    Replies:
    8
    Views:
    131
    Walter Roberson
    Apr 28, 2004
  5. vineet
    Replies:
    3
    Views:
    107
    vineet
    Feb 1, 2008
Loading...

Share This Page