#!/bin/perl

# Perl IO basics

# copy a file (ascii)

($infile, $outfile) = @ARGV;  # interpret command line params

open(infd,$infile);       # open for reading
open(outfd,">$outfile");  # open for writing (use >> for append)

@lines = <infd>;          # read entire file ($lines =<infd> reads one line)
print outfd @lines;

close(infd); close(outfd);


# but what about binary IO?
# how to read 4 bytes and assign to an int?
# one solution is to just read in strings:

open(infd,"testfile");
$x += <infd>;
print $x, "\n";  # works, but the integer must come in as a string, e.g. "12".
close(infd);

# Binary IO requires sysread, syswrite, which are basically the same as the
# read and write operations of C:

# binary file copy - copies 1K at a time.

$outfile = $outfile . ".bin";
open(infd,$infile);       # open for reading
open(outfd,">$outfile");  # open for writing (use >> for append)

my $bytesread = 1024;
my $buffer = "";

while ($bytesread == 1024)
  {
    $bytesread = sysread infd, $buffer, 1024;
    if ($bytesread > 0) {syswrite outfd, $buffer, $bytesread}
  }

close(infd); close(outfd);


# problem: what if you want to read in 8 bytes and interpret that as a double?
open(infd,"testc");
#binmode infd;    # no apparent effect.

my ($n,$x);
sysread infd, $x, 4;
print $x, "\n";    # prints the integer as a string of 4 chars
 
# solution: need to "unpack" the string:
$x = unpack("i",$x);
print $x, "\n";   # now get 650000, the number written by the C program.


sysread infd, $n, 8;  # read as a double
print $n, "\n";
# at this point, $n is interpreted as a string (meaningless).

#$n = $n*1.0;  # unfortunately, $n is now 0 when we force the issue!

$n = unpack("d",$n);   # d for double, i for integer, c for char, C for unsigned
print $n, "\n";

#similarly, we have to pack the data when doing binary output:
$x = 6.67;
my $y = pack("d",$x);
#print $y, "\n";   # will print garbage.

close(infd);


