Reputation: 35
I don't know why the following code outputs a blank file. I am running Windows 8. I've received help from this community for previous perl help and this is just what I've been able to put together with the help I've received. However, I can't figure out where this script goes awry.
#! perl
use strict;
use warnings;
use HTML::FormatText;
use LWP::Simple;
my $dateField = 'date=2018-12-31';
my $currency = "USD";
my $filename = 'C:\Users\Name\Desktop\doc3.txt';
my $address = "https://www.oanda.com/rates/api/v1/rates/$currency.csv?api_key=gpolonsky&decimal_places=4&$dateField&fields=averages"e=USD"e=AUD"e=BRL"e=CAD"e=GBP"e=CHF"e=CNY"e=DKK"e=HKD"e=INR"e=IDR"e=ILS"e=JPY"e=MXN"e=NOK"e=PHP"e=PLN"e=SGD"e=sKK"e=ZAR"e=KRW"e=SEK"e=TWD"e=THB"e=EUR"e=MYR"e=NZD"e=SAR"e=TRY"e=RUB"e=CZK"e=AED"e=CLP"e=EGP"e=MAD"e=NGN"e=OMR"e=QAR";
my $content = get($address);
my $s = 1;
defined $content or die "Cannot read '$address': $!";
$content =~ s/^[^\n]*\n//s;
$content =~ s/^/20181231,/gm; # The m option makes ^ match at the start of each line
$content =~ s/,2018-12-3[0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\+0000*//g;
$content =~ s/([A-Z][A-Z][A-Z]),[0-9]*\.[0-9][0-9][0-9][0-9]/$1/g;
my $string = HTML::FormatText->format_string(
$content,
leftmargin => 0,
rightmargin => 23,
);
open(my $file, '>', $filename) or die $!;
print $file $string;
my @curOrd = qw( USD AUD BRL GBP CAD CNY DKK HKD INR IDR ILS JPY MXN NOK PHP PLN SGD SKK ZAR KRW SEK CHF TWD THB EUR MYR NZD SAR TRY RUB CZK AED CLP EGP MAD NGN OMR QAR );
my %data;
my $infile = 'C:\Users\Name\Desktop\doc3.txt';
my $outfile = 'file2.txt';
open (my $in, "<", $infile ) || die "can't open $infile file";
while (my $line = <$in>) {
push(@{$data{(split ',', $line)[2]}}, $line);
}
print $infile;
close $in;
open (my $out, ">", $outfile) || die "can't open $outfile file";
foreach my $curr (@curOrd) {
foreach my $line (@{$data{$curr}}) {
print $out $line;
}
}
close $out;
Upvotes: 1
Views: 100
Reputation: 69224
Your problem is that you need to explicitly close()
the file you're writing to before you can re-open it to read from it.
But that whole intermediate file is pointless (as I've suggested before). Just process all the data in memory before writing it to your output file.
use strict;
use warnings;
use feature 'say';
use LWP::Simple;
my $dateField = 'date=2018-12-31';
my $currency = "USD";
my $filename = 'doc3.txt';
my $address = "https://www.oanda.com/rates/api/v1/rates/$currency.csv?"
. "api_key=gpolonsky&decimal_places=4&$dateField&fields=averages&"
. "quote=USD"e=AUD"e=BRL"e=CAD"e=GBP&"
. "quote=CHF"e=CNY"e=DKK"e=HKD"e=INR&"
. "quote=IDR"e=ILS"e=JPY"e=MXN"e=NOK&"
. "quote=PHP"e=PLN"e=SGD"e=sKK"e=ZAR&"
. "quote=KRW"e=SEK"e=TWD"e=THB"e=EUR&"
. "quote=MYR"e=NZD"e=SAR"e=TRY"e=RUB&"
. "quote=CZK"e=AED"e=CLP"e=EGP"e=MAD&"
. "quote=NGN"e=OMR"e=QAR";
my $content = get($address);
# I've removed $! from the die() error below. $! is the last
# *operating system* error. And making an HTTP request is not
# an operating system operation - so the contents will have no
# connection to the results of our GET request.
defined $content or die "Cannot read '$address'";
$content =~ s/^[^\n]*\n//s;
$content =~ s/^/20181231,/gm; # The m option makes ^ match at the start of each line
$content =~ s/,2018-12-3[0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\+0000*//g;
$content =~ s/([A-Z][A-Z][A-Z]),[0-9]*\.[0-9][0-9][0-9][0-9]/$1/g;
my @curOrd = qw( USD AUD BRL GBP CAD CNY DKK HKD INR IDR ILS JPY MXN
NOK PHP PLN SGD SKK ZAR KRW SEK CHF TWD THB EUR MYR
NZD SAR TRY RUB CZK AED CLP EGP MAD NGN OMR QAR );
my $i = 1;
my %curr_lookup = map { $_ => $i++ } @curOrd;
my @data = map { [ split /,/ ] } split /\n/, $content;
my $outfile = 'file2.txt';
@data = sort { $curr_lookup{$a->[2]} <=> $curr_lookup{$b->[2]} }
@data;
open my $out, '>', $outfile or die "Can't open $outfile for writing: $!";
say $out join ',', @$_ for @data;
Upvotes: 4
Reputation: 51
You need to close $file after you fetch the data from the server and are writing it to a file:
open(my $file, '>', $filename) or die $!;
print $file $string;
close($file) # Add this line
I also had to use http:// instead of https:// in $address, but I'm on a CentOS box with an old LWP install that doesn't seem to do TLS.
Upvotes: 5