Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Copying binary files

Posted on 1998-10-15
7
Medium Priority
?
239 Views
Last Modified: 2010-03-05
I am writing a Perl program that runs on NT. I have NFS mounted unix filesystems. I will need to copy binary files from the NT system to the Unux filesystem. I have written a subroutines that accepts two parameters, the full source path including filename, and the destination path. I suspect that I would be opening a filehandle to the destination file and opening another to the source. I guess that I would then simply print one to the other, but I think I need binary mode somewhere.

I hope this is clear enough.
Thanx
Angel
0
Comment
Question by:aleyva
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
7 Comments
 
LVL 5

Accepted Solution

by:
b2pi earned 800 total points
ID: 1205351
perldoc -f binmode

will tell you what you might be looking for.  However, since you have
file systems nfs mounted, why not just do

system('copy /b src_file_on_nfs_fs dst_file_on_local_storage');

unless you're doing this from the UNIX side, in which case it would be

system('cp src_file_on_remote_NT_storage dst_file_on_unix_fs ');

you might also want to check out using Net::FTP, but you may not have
servers set up.

If you're convinced you want to do it by hand, try (Note that this is
off the top of my head, some clean up may be necessary, your mileage
may vary, offer not valid in the state of Utah)

sub MyCP ( $$ );

sub MyCP ( $$ ) {

    my($src, $dst) = @_;

    my($error) = 0;
    if (!-f "$src") {
       carp "MyCP: Invalid src file '$src'";
       $error ++;
    }
    if (!-f "$dst") {
       carp "MyCP: Invalid dst file '$dst'";
       $error ++;
    }
    return undef if $error;

    open(SRC, "<$src") || $error++;
    if ($error) {
       carp "Unable to open src file '$src' : $!";
       return undef;
    }
    open(DST, ">$dst") || $error++;
    if ($error) {
       carp "Unable to open dst file '$dst' : $!";
       close(SRC);
       return undef;
    }
    binmode SRC;
    binmode DST;

    my($count) = 64*1024;
    my($bcount, $rcount, $wcount, $buffer, $rcount);

    for ($bcount = -s $src; $bcount; $bcount -= $wcount) {
          $rcount = sysread(SRC, $buffer, $count);
      $wcount = undef;
      if (!defined($rcount)) {
         carp "src read failed: $!";
      } else {
          $wcount = syswrite(DST, $buffer, $rcount);
          if (!defined($wcount) || $wcount != $rcount) {
             carp "dst write failed: $!";
          }
      }
      if (!defined($wcount) || $wcount != $rcount) {
          close(SRC);
          close(DST);
          return undef;
        }
    }
    close(SRC);
    close(DST);
    return 1;
}

0
 

Author Comment

by:aleyva
ID: 1205352
b2pi, Why don't you have any real profile data? Anyway,

I have a couple of questions/comments.
First of all, what is the carp () command doing?

Next, I have done the following and it works, so I would simply want to ask why it is or isn't a good idea to do it this way.

      open (SRC,"$source");
      open (DEST,">$destination");
      binmode (SRC);
      binmode (DEST);
      print DEST <SRC>;
      close (SRC);
      close (DEST);

Again, this works because I am able to read the files on the UNIX end.

I tried the system ("copy /b $source $destination"); command, but the files never appeared, this is why I am now trying with perl. Not only that, it makes it more portable.

One more, would it be asking too much to have you comment the code? (You must be rolling your eyes by now with that one).

Appreciated
Angel

PS    I increased the points.
0
 
LVL 5

Expert Comment

by:b2pi
ID: 1205353
1.) Why do I need profile data?
2.) carp issues warnings with a bit of trace info.  I note that I
forgot that at the top of the code there has to be a


use Carp;

line.  Take a look at

perldoc Carp

for more information. (Note that, as with warn, you can defined a
$SIG__WARN__} handler to suppress messages)

3.) There's probably no problem with your code, save for two
bugaboos. First, no error handling, and no way to determine if the
copy worked (or, if it didn't, where, and why not).  Secondly, it will
read the entire file into memory as one chunk.  That could be a bit of
a problem if memory resources are .... constrained.  Suppose you have
a 64M machine, and a 128M file.  Even with virtual memory, you're
going to be waiting a long, long time.

4.) Comment?  It's kind of small, but...

use strict;
use Carp;

## Prototype to put at the top of code
sub MyCP ( $$ );


## Intervening code..., including that which calls MyCP
## like
##
##    die "MyCP failure" if !MyCP($src, $dst)
##

sub MyCP ( $$ ) {
    my($src, $dst) = @_;
    my($error) = 0;
    ## Ensure that the source file exists
    if (!-f "$src") {
        carp "MyCP: Invalid src file '$src'";
        $error ++;
    }
    ## Ensure that the destination file exists
    if (!-f "$dst") {
        carp "MyCP: Invalid dst file '$dst'";
        $error ++;
    }
    return undef if $error;
    ## Open the source file
    open(SRC, "<$src") || $error++;
    if ($error) {
        carp "Unable to open src file '$src' : $!";
        return undef;
    }
    ## Open the destination file
    open(DST, ">$dst") || $error++;
    if ($error) {
        carp "Unable to open dst file '$dst' : $!";
        close(SRC);
        return undef;
    }
    ## Set both source and destination files to binmode
    binmode SRC;
    binmode DST;
    ## Define a constant for maximum read size
    my($count) = 64*1024;
    ## declare some variables (byte count, read count, write count,
    ## a buffer for reads and writes, and bytes remaining)
    my($bcount, $rcount, $wcount, $buffer, $rcount);
    ## Note that -s $src returns the size of the file $src
    for ($bcount = -s $src; $bcount; $bcount -= $wcount) {
      ## Read the data, $rcount is the number of bytes read
        $rcount = sysread(SRC, $buffer, $count);
        $wcount = undef;
      ## Complain on error
        if (!defined($rcount)) {
            carp "src read failed: $!";
        } else {
          ## Write the data, $wcount is the number of bytes written
            $wcount = syswrite(DST, $buffer, $rcount);
          ## Complain on error
            if (!defined($wcount) || $wcount != $rcount) {
                carp "dst write failed: $!";
            }
        }
      ## Complain and return on error
        if (!defined($wcount) || $wcount != $rcount) {
            close(SRC);
            close(DST);
            return undef;
        }
    }
    ## clean up
    close(SRC);
    close(DST);
    # Done
    return 1;
}

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 84

Expert Comment

by:ozo
ID: 1205354
b2pi, if you're not going to handle partial writes from the sysewrite, it may be safer to use print, which handles all that for you.
0
 

Author Comment

by:aleyva
ID: 1205355
b2pi,

The reason for the profile, is primarily to know your background/experience, and a name, but no big deal.

I implemented your solution, and it works like a champ almost. I don't think that it is your code as much as it might be the file, but I have a postscript file that was saved on a MAC as BINARY Postscript. The programs loops forever trying to write the file even though it is returning 0 values for rcount and wcount. I simply put an check if these values are 0, then exit.

Thanx again,
Angel
0
 
LVL 5

Expert Comment

by:b2pi
ID: 1205356
ozo, I thought I was handling partial results from the write ($wcount
!= $rcount). It is true that I could retry the write, but, really,
I don't think I've ever had a need.

I find it curious that a sysread could return 0 bytes on a proper call...
0
 
LVL 84

Expert Comment

by:ozo
ID: 1205357
You may not have ever had a signal sent to you during a syswrite
(write is different, don't try to mix write and syswrite calls on the same filehandle)
But that doesn't mean you will never have the need.
0

Featured Post

New benefit for Premium Members - Upgrade now!

Ready to get started with anonymous questions today? It's easy! Learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

664 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question