Both Reading and writing to a file - perl

I am new to perl and am trying to read and write to a csv file in perl. But nothing happens can some one help me where the problem is. I am able to read without a problem using '<' but I am unable to write.
use strict;
use warnings;
use Text::CSV_XS;
my $file = 'file.csv';
my $csv = Text::CSV_XS->new();
open (InCSV, '+>>', $file) or die $!;
while (<InCSV>) {
if ($csv->parse($_)) {
my #columns = $csv->fields();
if($columns[1] eq "01") {
my $str = "Selected $columns[6] \n ";
push(#columns,$str);
print InCSV join("," , #columns), "\n";
}
} else {
my $err = $csv->error_input;
print "Failed to parse line: $err";
}
}
close InCSV;

Opening a file in +>> mode will seek to the end of the file, so there will be nothing to read unless you seek back to the beginning (or the middle) of the file. To open in read/write mode with the file cursor at the beginning of the file, use +< mode.
That said, you probably want to rethink your approach to this problem. It looks like you are trying to read a row of data, modify it, and write it back to the file. But the way you have done it, you are overwriting the next row of data rather than the row you have just read, and anyway the new data is longer (has more bytes) than the old data. This is certain to corrupt your data file.
Some better approaches might be to
read and process all data first, then close and overwrite the input with processed data
write data to a temporary file while you are processing it, then overwrite the input with the temporary file (see also about the perl interpreter's in-place editing mode)
use a module like Tie::File to handle the line-based I/O for this task

Related

Reading a CSV file and writing to a CSV file

use Text::CSV;
$csv = Text::CSV->new;
open(HIGH, "+>Hardtest.csv") || die "Cannot open ticket $!\n"; #reads the high file
while(<HIGH>)
{
print "Printing High Priority Tickets ...\n";
sleep(1);
print <HIGH>;
}
close(HIGH);
here is my code, i am trying to read a csv and write to it, however i cant seem to read the CSV file, help would be appreciated, thanks!
OK, lots of things here.
Always use strict and use warnings.
You're opening the CSV file write mode (append mode?). Don't do that, if you're just reading from it.
Don't use || die, use or die.
Finally, don't print <HIGH>, instead print $_.
I've modified your code a bit:
#!/usr/bin/perl -w
use strict;
use Text::CSV;
my $csv = Text::CSV->new;
open(HIGH, "+<Hardtest.csv") || die "Cannot open ticket $!\n"; #reads the high file
while(<HIGH>)
{
print "Printing High Priority Tickets ...\n";
print $_;
sleep(1);
}
print HIGH "9,10,11,12\n";
close(HIGH);
Let me explain:
1. "+>" will open the file in read/write mode, BUT will also overwrite the existing file. Hence, In your code, while loop is never entered. I've changed that to "+<" which means read/write in append mode.
2. Second last statement, in above code, will append new content to the CSV file.

Perl script -- Multiple text file parsing and writing

Suppose i have this directory full of text files (raw text). What i need is a Perl script that will parse the directory (up2bottom) text files one by one and save their contents in a new single file, appointed by me. In other words i simply want to create a corpus of many documents. Note: these documents have to be separated by some tag e.g. indicating the sequence in which they were parsed.
So far i have managed to follow some examples and i know how to read, write and parse text files. But i am not yet in position to merge them into one script and handle many text files. Can you please provide some assistance. thanks
edit:
example code for writing to a file.
#!/usr/local/bin/perl
open (MYFILE, '>>data.txt');
print MYFILE "text\n";
close (MYFILE);
example code for reading a file.
#!/usr/local/bin/perl
open (MYFILE, 'data.txt');
while (<MYFILE>) {
chomp;
print "$_\n";
}
close (MYFILE);
I've also find out about the foreach function which can be used for tasks as such, but still don't know how to combine them and achieve the result explained in the description.
The important points in this suggestion are:
the "magic" diamond operator (a.k.a. readline), which reads from each file in *ARGV,
the eof function, which tells if the next readline on the current filehandle will return any data
the $ARGV variable, that contains the name of the currently opened file.
With that intro, here we go!
#!/usr/bin/perl
use strict; # Always!
use warnings; # Always!
my $header = 1; # Flag to tell us to print the header
while (<>) { # read a line from a file
if ($header) {
# This is the first line, print the name of the file
print "========= $ARGV ========\n";
# reset the flag to a false value
$header = undef;
}
# Print out what we just read in
print;
}
continue { # This happens before the next iteration of the loop
# Check if we finished the previous file
$header = 1 if eof;
}
To use it, just do: perl concat.pl *.txt > compiled.TXT

Print a file until certain characters found

My script is fetching data from .txt file.
I need to print the data until I find "MSISDN1" in that file.
The code I have executed is:
open (SERVICE, "Service Req.txt") || die "Cannot open service req file $!\n";
my #serv=<SERVICE>;
open(LOG, ">>logfile.txt");
foreach $ser_req(#serv) {
#until ($ser_req =~ m/MSISDN1/g)
{
print $conn $ser_req;
print LOG $ser_req;
print $ser_req;
}
close(LOG);
close (SERVICE) || die "Cannot close service req file $!\n";
The code does not run well, when the until condition is un-commented.
There is a very minute error in the code.
The until loop is not supposed to be applied.
until starts a loop. You probably want
last if $ser_req =~ /MSISDN1/;
instead of the (until) loop. You'll need to balance your braces { ... } too.
You could sensibly close SERVICE immediately after slurping the file into memory. It's a good idea to release resources such as files as quickly as you can. If you decide not to slurp the whole file (which would probably be better, especially if the marker text occurs near the beginning of big files), then you replace the foreach loop with while (<SERVICE>) or something similar.

Perl Read/Write File Handle - Unable to Overwrite

I have a Perl Script which performs a specific operation and based on the result, it should update a file.
Basic overview is:
Read a value from the file handle, FILE
Perform some operation and then compare the result with the value stored in INPUT file.
If there is a change, then update the file corresponding to File Handle.
When I say, update, I mean, overwrite the existing value in INPUT file with the new one.
An overview of the script:
#! /usr/bin/perl
use warnings;
use diagnostics;
$input=$ARGV[0];
open(FILE,"+<",$input) || die("Couldn't open the file, $input with error: $!\n");
# perform some operation and set $new_value here.
while(<FILE>)
{
chomp $_;
$old_value=$_;
if($new_value!=$old_value)
{
print FILE $new_value,"\n";
}
}
close FILE;
However, this appends the $new_value to the file instead of overwriting it.
I have read the documentation in several places for this mode of FILE Handle and everywhere it says, read/write mode without append.
I am not sure, why it is unable to overwrite. One reason I could think of is, since I am reading from the handle in the while loop and trying to overwrite it at the same time, it might not work.
Thanks.
your guess is right. You first read the file so file pointer is actually in the position of end of old value. I didn't try this myself, but you can probably seek file pointer to 0 before print it out.
seek(FILE, 0, 0);
You should add truncate to your program along with seek.
if( $new_value != $old_value )
{
seek( FILE, 0, 0 );
truncate FILE, 0;
print FILE $new_value,"\n";
}
Since the file is opened for reading and writing, writing a shorter $new_value will leave some of the $old_value in the file. truncate will remove it.
See perldoc -f seek and perldoc -f truncate for details.
you have to close the file handle and open a different one (or the same one if you like) set to the output file. like this.
close FILE;
open FILE, ">$input" or die $!;
...
close FILE;
that should do the trick

Reading from file using Perl

I am learning Perl and have looked up this question but haven't been able to get it to work for me although it terminates without error.
I enter a file that it should want (name-0-0-0) but it just skips the while loop altogether.
open FILE, '+>>userinfo.txt';
print("What is your name?");
$name = <>;
chomp $name;
while (<FILE>) {
chomp;
($nameRead,$wins, $losses, $cats) = split("-");
if ($nameRead eq $name){
print("Oh hello $name, your current record is $wins wins - $losses losses - $cats ties");
print("Would you like to play again? type y for yes or n for no\n");
$bool = <>;
if ($bool == "y"){
print("Okay let's play!");
play();
exit();
}
else {
printf("well fine goodbye!");
exit();
}
}
}
Well it seems my problem was indeed related to the +>>. I am trying to add on to the file, but I wanted to be able to write, not just append. I changed it to +< and everything worked great. Thanks guys I really appreciate it!
Your primary problem is that you have chosen an arcane open mode for userinfo.txt, which will allow you to open an existing file for both read and write but create a new file if it doesn't exist.
You must always check whether a file open has succeeded, and it looks like all you want to do is read from this file, so you want
open FILE, '<', 'userinfo.txt' or die $!;
You must also always add
use strict;
use warnings;
to the top of your program, and declare all variables with my at their first point of use.
Once you have made these changes you will most likely understand yourself what is going wrong, but if you have further problems please post your modified code.
I appears like you're using the wrong syntax to open the file for reading. Try
use autodie qw(:all);
open my $FILE, '<', '/path/to/file';
The syntax you're using opens a file for appending.
Why are you opening the file in +>> mode? That mode opens your file for input and output, but sets the filehandle cursor to the end of the file. Even experienced Perl programmers rarely have a need to do that.
Since the filehandle is positioned at the end of the file when you open it, you won't get anything when you attempt to read from it.
Is there a reason you aren't just saying open FILE, '<', 'userinfo.txt' ?
The following says while you're reading the file and it hasn't reached the end of file:
while (<FILE>) {
...
}
You might want to remove the while loop entirely and just do everything inside it.
Edit/Alternative Solution:
The real reason nothing was happening is because when you use +>>, it opens the file up for read/append as you'd expect, but it immediately sets the cursor at the end of the file. So that when you encounter the while (<FILE>) { ... } there's nothing to read.
One solution would be to reset the file cursor position:
open FILE, '+>>userinfo.txt';
seek(FILE,0,0); # set the file cursor at the top