Perl. I cannot write on a file. The file stays empty - perl

I wrote the code below.
I cannot find any error in it.
But
say $valid $1;
does not work. $valid file is empty when the program finishes.
What's wrong?
Thanks in advance! ^^
#!/usr/bin/perl
use 5.012;
use strict;
use warnings;
use LWP::Simple;
open my $input, '<', 'c:\perl\015_JiraGet\addrHDP.txt' or die "Cannot read: $!\n";
open my $valid, '<', 'c:\perl\015_JiraGet\valid.txt' or die "Cannot read: $!\n";
my #totalReport;
my $eachAddr;
my $copyFile;
my $copyFilePath = 'c:\perl\015_JiraGet\HADOOP XML\\';
my $tempFile;
my $tempFilePath = 'c:\perl\015_JiraGet\temp.txt';
my $analyzed;
my $analyzedPath = 'c:\perl\015_JiraGet\analyzed - HADOOP.txt';
my $undefCheck;
my $i = 0;
my $j = 0;
my $title = 'temp';
my $dup = 0;
while(<$input>) { chomp; push #totalReport, $_; }
foreach(#totalReport)
{
$eachAddr = $_;
$undefCheck = get($eachAddr);
if(defined($undefCheck) == 0) { next; }
# Copy one XML file to 'temp.txt' and then close the file.
open $tempFile, '>', $tempFilePath or die "Cannot open 1: $!\n";
print $tempFile get($eachAddr);
close $tempFile;
# If the entry is a duplicate, go on to the next entry
open $tempFile, '<', $tempFilePath or die "Cannot open 2: $!\n";
($title, $dup) = isDuplicate($tempFile, $title);
if($dup == 1) { close $tempFile; next; }
close $tempFile;
say ++$i . "th report!!!";
# Copy one XML file to HDD.
if($eachAddr =~ /.*\/(.*)/)
{
say $valid $1;
open $copyFile, '>', $copyFilePath . $1 or die "Cannot open 3: $!\n";
print $copyFile get($eachAddr);
close $copyFile;
}
# If the entry is NOT fixed or resolved, go on to the next entry
open $tempFile, '<', $tempFilePath or die "Cannot open 4: $!\n";
if(isFixCloseResolve($tempFile) == 0) { close $tempFile; next; }
close $tempFile;
# Analyze one entry
open $tempFile, '<', $tempFilePath or die "Cannot open 5: $!\n";
open $analyzed, '>>', $analyzedPath or die "Cannot open 6: $!\n";
analyzeOneReport($tempFile, $analyzed);
close $tempFile;
close $analyzed;
say ' ' . ++$j . "th fixed & closed report!!!";
}
say "$i total reports.";
say "$j total fixed & closed reports.";
close $input;
close $valid;
say "Finished!";
sub isDuplicate
{
my $iReport = $_[0];
my $title = 'temp';
my $dup = 0;
while(<$iReport>)
{
if ($_ =~ /.*\<title>(.*)\<\/title>/)
{
if($1 ne 'ASF JIRA') { $title = $1; if($title eq $_[1]) { $dup = 1; } last; }
}
}
return ($title, $dup);
}
# returns 1 if an entry is a Bug and Fixed and Closed
sub isFixCloseResolve
{
my $iReport = $_[0];
my $isCloseResolve = 0;
my $isFixed = 0;
while(<$iReport>)
{
if ($_ =~ /.*\<status[^>]*>(.*)\<\/status>/) { if(($1 eq 'Closed')||($1 eq 'Resolved')) { $isCloseResolve = 1;} }
elsif($_ =~ /.*\<resolution[^>]*>(.*)\<\/resolution>/) { if($1 eq 'Fixed') { $isFixed = 1;} }
}
return $isCloseResolve * $isFixed;
}
sub analyzeOneReport
{
my $iReport = $_[0];
my $oReport = $_[1];
while(<$iReport>)
{
chomp;
if ($_ =~ /.*\<title>(.*)\<\/title>/) { if($1 ne 'ASF JIRA') { say $oReport "Title : $1"; } }
elsif($_ =~ /.*\<assignee username="(.*)">.*\<\/assignee>/) { say $oReport "Assignee: $1"; }
elsif($_ =~ /.*\<reporter username="(.*)">.*\<\/reporter>/) { say $oReport "Reporter: $1"; }
elsif($_ =~ /.*\<type[^>]*>(.*)\<\/type>/) { say $oReport "Type : $1"; }
elsif($_ =~ /.*\<priority[^>]*>(.*)\<\/priority>/) { say $oReport "Priority: $1"; }
elsif($_ =~ /.*\<created>(.*)\<\/created>/) { say $oReport "Created : $1"; }
elsif($_ =~ /.*\<resolved>(.*)\<\/resolved>/) { say $oReport "Resolved: $1"; }
}
say $oReport '--------------------------------------------';
}
--- Postscript ---
Oh, I was wrong on '>' part!! Thank you everyone!!
But when I changed that into '>', still nothing was written on the file 'DURING PROGRAM RUNNING TIME'.
So I was confused...and I found that Perl actually writes the contents to the file 'WHEN IT CLOSED THE FILE'.
So during running time, for 4~8 hours, I could not see anything in the file.
Data is written on the file when the file is closed.
That's one of the reason why I thought this code was not working. ^^;
Hope nobody else suffer from this problem again! :)

Here:
open my $valid, '<',....
you have opened $valid for reading. If you wish to write to the file, you must instead write:
open my $valid, '>',....
If you need to keep existing contents and write only to the end then instead use
open my $valid, '>>',....

You're only opening the file under the $valid file handle with read capabilities, as you can see from this line:
open my $valid, '<', 'c:\perl\015_JiraGet\valid.txt' or die "Cannot read: $!\n";
So nothing you write to the file will actually go into it. Change it to read/write (or append, if you need it, just use +>> instead of +> in the code below), and you should be good, as follows:
open my $valid, '+>', 'c:\perl\015_JiraGet\valid.txt' or die "Cannot read: $!\n";

I am going to review this code as if it had been posted to Code Review.
First off you are writing in Perl as if it were C. Which in general is not that bad, but it does mean that you are doing quite a bit more work than is necessary.
Instead of using this overly verbose, and potentially memory intensive:
my #totalReport
...
while(<$input>) { chomp; push #totalReport, $_; }
foreach(#totalReport)
{
$eachAddr = $_;
...
}
while( my $addr = <$input> ){
chomp $addr;
...
}
Notice how I've eliminated a variable, and made it so that it loops on the input once, instead of twice. It also doesn't keep the values in memory over the entire length of the program.
Instead of opening a file for writing, closing it, and opening it again:
my $tempFile;
open $tempFile, '>', $tempFilePath or die "Cannot open 1: $!\n";
print $tempFile get($eachAddr);
close $tempFile;
open $tempFile, '<', $tempFilePath or die "Cannot open 2: $!\n";
open my $tempFile, '+>', $tempFilePath or die "Can't open '$tempFilePath' with mode'+>': '$!'";
print $tempFile get($eachAddr);
seek $tempFile, 0, 0;
Instead of getting the text at the given URL twice, and using a weird defined test:
$undefCheck = get($eachAddr);
if(defined($undefCheck) == 0) { next; }
...
print $tempFile get($eachAddr);
my $text = get( $addr );
next unless defined $text;
...
print $tempFile $text;
Instead of a bunch of:
open ... or die ...;
I would use autodie.
use autodie;
...
# will now die on error and will tell you the file it fails on.
open my $fh, '<', $filename;
Another thing I would like to point out is that die "...\n" prevents die from appending the location of the error. The only time you should do that is if the default behaviour is unhelpful.
If you closed $tempFile before checking $dup this could be simpler:
if($dup == 1) { close $tempFile; next; }
close $tempFile;
close $tempFile;
next if $dup;
Instead of this repetitive block of code:
while(<$iReport>)
{
chomp;
if ($_ =~ /.*\<title>(.*)\<\/title>/) { if($1 ne 'ASF JIRA') { say $oReport "Title : $1"; } }
elsif($_ =~ /.*\<assignee username="(.*)">.*\<\/assignee>/) { say $oReport "Assignee: $1"; }
elsif($_ =~ /.*\<reporter username="(.*)">.*\<\/reporter>/) { say $oReport "Reporter: $1"; }
elsif($_ =~ /.*\<type[^>]*>(.*)\<\/type>/) { say $oReport "Type : $1"; }
elsif($_ =~ /.*\<priority[^>]*>(.*)\<\/priority>/) { say $oReport "Priority: $1"; }
elsif($_ =~ /.*\<created>(.*)\<\/created>/) { say $oReport "Created : $1"; }
elsif($_ =~ /.*\<resolved>(.*)\<\/resolved>/) { say $oReport "Resolved: $1"; }
}
use List::Util qw'max';
my #simple_tags = qw'title type priority created resolved';
my $simple_tags_length = max map length, #simple_tags, qw'assignee reporter';
my $simple_tags = join '|', #simple_tags;
...
while( <$iReport> ){
my($tag,$contents);
if( ($tag,$contents) = /<($simple_tags)[^>]*>(.*?)<\/\g{1}>/ ){
}elsif( ($tag,$contents) = /<(assignee|reporter) username="(.*?)">.*?<\/\g{1}>/ ){
}else{ next }
printf $oReport "%-${simple_tags_length}s: %s\n", ucfirst($tag), $contents;
}
While this code isn't any shorter, or clearer, it would be very easy to add another tag to compare against. So it isn't really better, as less repetitive.
I would like to point out that $_ =~ /.../ is better written as /.../.
You could use or instead of if/elsif/else with empty blocks.
...
while( <$iReport> ){
/<($simple_tags)[^>]*>(.*?)<\/\g{1}>/
or /<(assignee|reporter) username="(.*?)">.*?<\/\g{1}>/
or next;
my($tag,$contents) = ($1,$2);
printf $oReport "%-${simple_tags_length}s: %s\n", ucfirst($tag), $contents;
}
It might be best to combine them into a single regex using /x and (?<NAME>REGEX) syntax with %- or %+.
...
while( <$iReport> ){
/
(?:
# simple tags
< (?<tag> $simple_tags ) [^>]* >
# contents between tags
(?<contents> .*? )
|
# tags with contents in `username` attribute
<
(?<tag> assignee|reporter )
[ ]
# contents in `username` attribute
username = "(?<contents> .*? )"
>
.*? # throw out stuff between tags
)
<\/ \g{tag} > # end tag matches start tag
/x or next; # skip if it doesn't match
printf $oReport "%-${simple_tags_length}s: %s\n", ucfirst($+{tag}), $+{contents};
}
Or even use (DEFINE) (I'll leave that as an exercise for the reader since this is already fairly long).
Perhaps the worst part of the code is that you define almost all of you variables up-front.
my #totalReport;
my $eachAddr;
my $copyFile;
my $copyFilePath = 'c:\perl\015_JiraGet\HADOOP XML\\';
my $tempFile;
my $tempFilePath = 'c:\perl\015_JiraGet\temp.txt';
my $analyzed;
my $analyzedPath = 'c:\perl\015_JiraGet\analyzed - HADOOP.txt';
my $undefCheck;
my $i = 0;
my $j = 0;
my $title = 'temp';
my $dup = 0;
This means that you are practically using global variables. While some of these appear to need to be defined there, some of them don't, and therefore shouldn't be defined there. You should really be defining your variables at the point you need them, or at least at the beginning of the block where you need them.
The reason you aren't getting the output until the file is closed is because Perl buffers the output.
Perl normally buffers output so it doesn't make a system call for every bit of output. By saving up output, it makes fewer expensive system calls. …
- perlfaq5
The old way to turn off buffering is to select the file for output and set $| to a non-zero value, and then re-select the original output.
{
my $previous_default = select($file); # save previous default output handle
$| = 1; # autoflush
select($previous_default); # restore previous default output handle
}
The new way is to use $file->autoflush which comes from IO::Handle.
(The module will get automatically loaded for you on recent versions of Perl 5)
You can also flush the output when you choose by using flush or $file->flush.
IO::Handle also adds a $file->printflush which turns on autoflush temporarily during the print.

Related

Perl - substring keywords

I have a text file where is lot of lines, I need search in this file keywords and if exist write to log file line where is keywords and line one line below and one above the keyword. Now search or write keyword not function if find write all and I dont known how can I write line below and above. Thanks for some advice.
my $vstup = "C:/Users/Omega/Documents/Kontroly/testkontroly/kontroly20220513_154743.txt";
my $log = "C:/Users/Omega/Documents/Kontroly/testkontroly/kontroly.log";
open( my $default_fh, "<", $vstup ) or die $!;
open( my $main_fh, ">", $log ) or die $!;
my $var = 0;
while ( <$default_fh> ) {
if (/\Volat\b/)
$var = 1;
}
if ( $var )
print $main_fh $_;
}
}
close $default_fh;
close $main_fh;
The approach below use one semaphore variable and a buffer variable to enable the desired behavior.
Notice that the pattern used was replaced by 'A` for simplicity testing.
#!/usr/bin/perl
use strict;
use warnings;
my ($in_fh, $out_fh);
my ($in, $out);
$in = 'input.txt';
$out = 'output.txt';
open($in_fh, "< ", $in) || die $!."\n";
open($out_fh, "> ", $out) || die $!;
my $p_next = 0;
my $p_line;
while (my $line = <$in_fh>) {
# print line after occurrence
print $out_fh $line if ($p_next);
if ($line =~ /A/) {
if (defined($p_line)) {
# print previous line
print $out_fh $p_line;
# once printed undefine variable to avoid printing it again in the next loop
undef($p_line);
}
# Print current line if not already printed as the line follows a pattern
print $out_fh $line if (!$p_next);
# toggle semaphore to print the next line
$p_next = 1;
} else {
# pattern not found.
# if pattern was not detected in both current and previous line.
$p_line = $line if (!$p_next);
$p_next = 0;
}
}
close($in_fh);
close($out_fh);

how to count the number of specific characters through each line from file?

I'm trying to count the number of 'N's in a FASTA file which is:
>Header
AGGTTGGNNNTNNGNNTNGN
>Header2
AGNNNNNNNGNNGNNGNNGN
so in the end I want to get the count of number of 'N's and each header is a read so I want to make a histogram so I would at the end output something like this:
# of N's # of Reads
0 300
1 240
etc...
so there are 300 sequences or reads that have 0 number of 'N's
use strict;
use warnings;
my $file = shift;
my $output_file = shift;
my $line;
my $sequence;
my $length;
my $char_N_count = 0;
my #array;
my $count = 0;
if (!defined ($output_file)) {
die "USAGE: Input FASTA file\n";
}
open (IFH, "$file") or die "Cannot open input file$!\n";
open (OFH, ">$output_file") or die "Cannot open output file $!\n";
while($line = <IFH>) {
chomp $line;
next if $line =~ /^>/;
$sequence = $line;
#array = split ('', $sequence);
foreach my $element (#array) {
if ($element eq 'N') {
$char_N_count++;
}
}
print "$char_N_count\n";
}
Try this. I changed a few things like using scalar file handles. There are many ways to do this in Perl, so some people will have other ideas. In this case I used an array which may have gaps in it - another option is to store results in a hash and key by the count.
Edit: Just realised I'm not using $output_file, because I have no idea what you want to do with it :) Just change the 'print' at the end to 'print $out_fh' if your intent is to write to it.
use strict;
use warnings;
my $file = shift;
my $output_file = shift;
if (!defined ($output_file)) {
die "USAGE: $0 <input_file> <output_file>\n";
}
open (my $in_fh, '<', $file) or die "Cannot open input file '$file': $!\n";
open (my $out_fh, '>', $output_file) or die "Cannot open output file '$output_file': $!\n";
my #results = ();
while (my $line = <$in_fh>) {
next if $line =~ /^>/;
my $num_n = ($line =~ tr/N//);
$results[$num_n]++;
}
print "# of N's\t# of Reads\n";
for (my $i = 0; $i < scalar(#results) ; $i++) {
unless (defined($results[$i])) {
$results[$i] = 0;
# another option is to 'next' if you don't want to show the zero totals
}
print "$i\t\t$results[$i]\n";
}
close($in_fh);
close($out_fh);
exit;

Why I am not getting "success" with this program?

I have written the following program with the hope of getting success. But I could never get it.
my $fileName = 'myfile.txt';
print $fileName,"\n";
if (open MYFILE, "<", $fileName) {
my $Data;
{
local $/ = undef;
$Data = <MYFILE>;
}
my #values = split('\n', $Data);
chomp(#values);
if($values[2] eq '9999999999') {
print "Success"."\n";
}
}
The content of myfile.txt is
160002
something
9999999999
700021
Try splitting by \s*[\r\n]+
my $fileName = 'myfile.txt';
print $fileName,"\n";
if (open MYFILE, "<", $fileName) {
my $Data;
{
local $/ = undef;
$Data = <MYFILE>;
}
my #values = split(/\s*[\r\n]+/, $Data);
if($values[2] eq '9999999999') {
print "Success";
}
}
If myfile.txt contain carriage return (CR, \r), it will not work as expected.
Another possible cause is trailing spaces before linefeed (LF, \n).
You don't need to read an entire file into an array to check one line. Open the file, skip the lines you don't care about, then play with the line you do care about. When you've done what you need to do, stop reading the file. This way, only one line is ever in memory:
my $fileName = 'myfile.txt';
open MYFILE, "<", $fileName or die "$filename: $!";
while( <MYFILE> ) {
next if $. < 3; # $. is the line number
last if $. > 3;
chomp;
print "Success\n" if $_ eq '9999999999';
}
close MYFILE;
my $fileName = 'myfile.txt';
open MYFILE, "<", $fileName || die "$fileName: $!";
while( $rec = <MYFILE> ) {
for ($rec) { chomp; s/\r//; s/^\s+//; s/\s+$//; } #Remove line-feed and space characters
$cnt++;
if ( $rec =~ /^9+$/ ) { print "Success\n"; last; } #if record matches "9"s only
#print "Success" and live the loop
}
close MYFILE;
#Or you can write: if ($cnt==3 and $rec =~ /^9{10}$/) { print "Success\n"; last; }
#If record 3 matches ten "9"s print "Success" and live the loop.

Perl find whether more than one string is in a log file then print

Hi just learning Perl so please forgive. What I am trying to do is if the log file contains one or more of these strings Failed, Error or Skipped then print out an error.(the log could have one or more of all of the strings in the arrary or just one instance) I have tried variations on the below code. It compiles but it only prints out Done.
#!perl=C:\IBM\RationalSDLC\ClearCase\bin\perl
my #matches = (
qr/"Failed"/,
qr/"Skipped"/,
qr/"Error"/,
);
$mylog = "email_log.txt";
open (LOG, "<$mylog") || die 'Could not OPEN $mylog file';
LOG_READER:
while (my $loglines = <$LOG>) {
if ($loglines =~ /#matches/) {
print "Error in the log\n";
last LOG_READER;
}
}
close($LOG);
print "\n Test is Done \n";
I have also tried
while ( $_ = <INPUT> ) {
if( $_ =~ #matches ){
print "\n Build Failed! \n";
}
}
thank you for any assistance
Modified code that works
This solution uses an array
#!perl=C:\IBM\RationalSDLC\ClearCase\bin\perl
my #matches = qr/Failed | Skipped | Error/x;
my $mylog = "email_log.txt";
open (LOG, "<$mylog") || die 'Could not OPEN $mylog file';
LOG_READER:
while (my $loglines = <LOG>) {
if ($loglines =~ /$matches/) {
print "Error in the log\n";
last LOG_READER;
}
}
close(LOG);
print "\n Test is Done \n";
This solution is what I used
#!perl=C:\IBM\RationalSDLC\ClearCase\bin\perl
use warnings;
use strict;
my $myfailures = qr/Failed | Skipped | Error/x;
my $mylog = "email_log.txt";
open (LOG, "<$mylog") || die 'Could not OPEN $mylog file';
LOG_READER:
while (my $loglines = <LOG>) {
if ($loglines =~ /$myfailures/) {
print "Error in the log\n";
last LOG_READER;
# last;
}
}
close(LOG);
print "\n Test is Done \n";
Another solution
#!perl=C:\IBM\RationalSDLC\ClearCase\bin\perl
use warnings;
use strict;
my $mylog = "email_log.txt";
open (INPUT, "<$mylog") || die 'Could not OPEN $mylog file';
LOG_READER:
while(<INPUT>) {
next unless /(Failed|Skipped|Error)/;
print "\n Build failed \n";
last;
}
close(INPUT);
print "\n Test is Done \n";
Solution #4
#!perl=C:\IBM\RationalSDLC\ClearCase\bin\perl
use warnings;
use strict;
my $matches = "Failed|Skipped|Error";
my $mylog = "email_log.txt";
open my $LOG, "<", $mylog|| die 'Could not OPEN $mylog file';
while (my $loglines = <$LOG>) {
if ($loglines =~ /$matches/) {
print "\n Error in the log\n";
last;
}
}
close($LOG);
print "\n Test is Done \n";
Thank you everyone for the contributions. They all worked really wish I could give everyone the correct answer. With the provided solutions I was able to get all the variations working.
if ($loglines =~ /#matches/) {
This is your problem. You cannot use an array as the regex to match against. Try this instead:
if ($loglines =~ /"(Failed|Skipped|Error)"/) {
while (my $loglines = <$LOG>) {
...
close($LOG);
Oh and this should be just LOG without the dollar signs.
With use strict; use warnings; you would get some better diagnostics. Get into the habit.
You are making this far too complicated. You really just need to do some reading on how regexps work, but its quite a simple problem to solve:
while(<INPUT>) {
next unless /"(Failed|Skipped|Error)"/;
print "\n Build failed \n";
last;
}
You could use array of regex but for this particular case it's not needed,
my $matches = qr/"Failed" | "Skipped" | "Error"/x;
and then
if ($loglines =~ /$matches/) { .. }
First of all. I would always use use warnings; use strict;.
I would also modify your open calls to use the 3-arg, lexical scoped version.
open my $fh, "<", $mylog;
What exactly are you trying to match here?
my #matches = (
qr/"Failed"/,
qr/"Skipped"/,
qr/"Error"/,
);
An example from your log file would help. You're trying to match these keywords wrapped in actual quotes. Is this what you intended?
email_log.txt example:
Your build "Failed"
"Skipping" foo.c
This will match with or without surrounding quotes:
my $matches = "Failed|Skipped|Error";
my $mylog = "email_log.txt";
open my $fh, "<", $mylog;
while (my $loglines = <$fh>) {
if ($loglines =~ /$matches/) {
print "Error in the log\n";
last;
}
}
close($fh);

Adding header of the first file to all the other split files in Perl

I need to add header of the first main file to all the split files. i.e I am able to get header for the 1st split file but i need it for all the split files, here I am splitting DAT file. Below is what i have done so for:
#!usr/bin/perl -w
my $chunksize = 25000000; # 25MB
my $filenumber = 0;
my $infile = "Test.dat";
my $outsize = 0;
my $eof = 0;
my $line = $_;
open INFILE, $infile;
open OUTFILE, ">outfile_".$filenumber.".dat";
while (<INFILE>) {
chomp;
if ($outsize > $chunksize) {
close OUTFILE;
$outsize = 0;
$filenumber++;
open (OUTFILE, ">outfile_".$filenumber.".dat")
or die "Can't open outfile_".$filenumber.".dat";
}
print OUTFILE "$_\n";
$outsize += length;
}
close INFILE;
You should always use warnings (in preference to the command-line -w) and use strict. That way many simple errors that you may otherwise have obverlooked will be flagged
Use the three-parameter form of open with lexical filehandles
Check the result of all open calls and flag errors containing the value of $! in a die string
Define constant values with the use constant pragma father than as Perl variables
The number of bytes printed to a filehandle can be evaluated using the tell function, so there is no need to keep your own count
To solve your specific problem, you should read and remember the first line of your input file, and print it to new output files every time they are opened
It is easier to keep track of the output files if you open them when you have new data to write and no open file, and close them when they are full or if you have reached the end of the input data
This program demonstrates the ideas and does what is required
use strict;
use warnings;
use constant INFILE => 'Test.dat';
use constant CHUNKSIZE => 25_000_000; # 25MB
open my $infh, '<', INFILE or die $!;
my $header = <$infh>;
my $outfh;
my $filenumber = 0;
while (my $line = <$infh>) {
unless ($outfh) {
my $outfile = "outfile_$filenumber.dat";
open $outfh, '>', $outfile or die "Can't open '$outfile': $!";
print { $outfh } $header;
$filenumber++;
}
print { $outfh } $line;
if (tell $outfh > CHUNKSIZE or eof $infh) {
close $outfh or die $!;
undef $outfh;
}
}
You need to store the header from the input file and print it every time a new file is opened:
use strict;
use warnings;
use autodie;
# initializations ...
open my $in, '<', $infile;
open my $out, '>', "outfile_${file_number}.dat";
my $header = <$in>; # Save the header...
chomp $header; # ... not strictly necessary
while ( <$in> ) {
chomp; # Not strictly necessary
if ( $outsize > $chunksize) {
close $out;
$outsize = 0;
$filenumber++;
open $out, '>', "outfile_${file_number}.dat";
print $out $header, "\n"; # Prints header at beginning of file
# Newline needed if $header chomped
}
print $out $_, "\n"; # Newline needed if $_ chomped
$outsize += length;
}