Re: read from a file and write into the same file
by almut (Canon) on Mar 02, 2008 at 17:32 UTC
|
As you're opening for append, the file pointer is positioned at the
end, so your while(<FILE>) does not read anything ('cos it's
already at EOF). And, as your print FILE ... is in the same
loop, it doesn't write anything either, because it doesn't execute at all...
BTW, it's generally a good idea to get into the habit of
always error checking with file operations, in particular with open:
my $filename = "test.txt";
open FILE, "+>>", $filename or die "Couldn't open file '$filename': $!
+";
Update: In short, what I think you want to achieve
(read from the beginning, write at the end?) cannot be done that
way, because a file handle does not maintain two file pointers...
Alternatingly reading one line then writing (inserting) one line doesn't work either,
because the write doesn't shift around the later parts of the file.
Rather, it simply overwrites at that position, which typically doesn't work well with
text files (due to different line lengths). To observe the effect
try opening with "+<".
| [reply] [d/l] [select] |
|
The file pointer is not guaranteed to be anything in particular between the open and the first write, IIRC.
| [reply] |
|
...
open("test.txt", O_RDWR|O_APPEND|O_CREAT|O_LARGEFILE, 0666) = 5
_llseek(5, 0, [57], SEEK_END) = 0
...
which I would interpret to mean that the file pointer is positioned.
(_llseek is a Linux-specific syscall)
| [reply] [d/l] [select] |
|
Re: read from a file and write into the same file
by DigitalKitty (Parson) on Mar 02, 2008 at 20:15 UTC
|
#Open the 'txt' file for reading
open FH, '<', "$file_name.txt" or die "Error:$!\n";
#Open the 'txt' file for writing. Creates the
#file_name if it doesn't already exist
#and will delete/overwrite a pre-existing file of the same name
open FH, '>', "$file_name.txt" or die "Error:$!\n";
#Open the 'txt' file for appending. Creates the
#file_name if it doesn't already exist
open FH, '>>', "$file_name.txt" or die "Error:$!\n";
#Open the 'txt' file for a 'read/write'.
#Will not create the file if it doesn't
#already exist and will not delete/overwrite
#a pre-existing file of the same name
open FH, '+<', "$file_name.txt" or die "Error:$!\n";
#Open the 'txt' file for a 'read/write'. Will create
#the file if it doesn't already exist and will
#delete/overwrite a pre-existing file
#of the same name
open FH, '+>', "$file_name.txt" or die "Error:$!\n";
#Open the 'txt' file for a 'read/append'. Will create
#the file if it doesn't already exist and will
#not delete/overwrite a pre-existing file
#of the same name
open FH, '+>>', "$file_name.txt" or die "Error:$!\n";
A few suggestions:
Always enable both the strict and warnings pragmas with use strict; and use warnings; respectively. When you perform a file close operation, it is beneficial to check the success or failure since a hardware error could result:
close FH or die "Error in closing the file ", __FILE__, " $!\n";
Hope this helps,
~Katie
| [reply] [d/l] [select] |
Re: read from a file and write into the same file
by CountZero (Bishop) on Mar 02, 2008 at 19:48 UTC
|
From the docs:If MODE is '>>', the file is opened for appending, again being created if necessary. Adding a '+' doesn't change the position of the file-pointer, so you are already at the end of the file.Your while(<FILE>) gets a boolean FALSE and you never enter the loop at all. Remember, the loop-test is done first! If you want to go through the loop at least once, you put the test at the end: do {
print $_;
print FILE "*****************";
} while (<FILE>)
Of course the first (and only) time through this loop the value of $_ has no relationship with the file being read and it may even contain a value from earlier in your program!
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] [d/l] [select] |
Re: read from a file and write into the same file
by chatur (Acolyte) on Mar 03, 2008 at 06:04 UTC
|
Hi Anonymous monk
In my view you want to read all the file and afterwards append to a file then you can do is create a two file handleing pointers.
First thing is to read the whole content of a file to a memory or simply display it out.
Afterwards do the appending work.
Here is the example for the sorting file contents that might help
#!/usr/bin/perl -w
if (@ARGV < 1 ) {
print "$0 <file>\n";
exit 1
}
$tmp_file=$ARGV[0];
open(TMP_INPUT_FILE, "<$tmp_file"); # open for input
my(@lines) = <TMP_INPUT_FILE>; # read file into list
close(TMP_INPUT_FILE);
open(TMP_OUTPUT_FILE, ">$tmp_file");
@lines = sort(@lines); # sort the list
my($line);
foreach $line (@lines) # loop thru list
{
print TMP_OUTPUT_FILE "$line"; # print in sort order
}
close(TMP_OUTPUT_FILE);
In the above example filename is supplied at the command line. | [reply] [d/l] |
|
It is considered better to use <code> ... </code> tags rather than <pre> ... </pre> around code. This will allow easy downloading of the code and assures sensible wrapping of overly long line of the code. Also I have a code colorizer which needs <code> ... </code> tags to know what to colorize.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] [d/l] [select] |
|
Thanks for your comment and updated it
| [reply] |
Re: read from a file and write into the same file
by akho (Hermit) on Mar 02, 2008 at 16:54 UTC
|
| [reply] |
Re: read from a file and write into the same file
by systems (Pilgrim) on Mar 03, 2008 at 10:01 UTC
|
Remember you can also use perl to edit files in-place.
> perl -p -i.bak -e "s/(.*)/$1\n****************/" test.txt
The above command will append a new line containing **************** after every line in the document.
Now I have a question for the more experienced Perlers, can I do in-place file substitution from inside a script using just Perl code. Or do I have to execute as a command line? I know I can execute a command line within a Perl script, but what I mean, can I do it otherwise, without going to the command line in any way?
| [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
... can I do in-place file substitution from inside a script
If using the feature behind the -i option from within a
script is what you mean... yes, you can. You can either put the
-i.bak on the shebang line, or set the corresponding $^I
special variable (as olus already mentioned). The latter allows a
little more flexibility, e.g. you could localise the effects
#!/usr/bin/perl
use strict;
use warnings;
sub edit_inplace {
local @ARGV = @_;
local $^I = ".bak";
# local $^I = ""; # no backup file
while (<>) {
s/(.*)/$1\n****************/;
print $_;
}
}
edit_inplace("test.txt");
BTW, even Perl doesn't do a real in-place edit (i.e. modify the
physically-same file). Rather, it opens, then renames (or
unlinks, when no backup extension is specified) the original
file, then opens a new file with the same name — at
least on Unix, where opened files continue to be accessible, even when
they're no longer associated with a directory entry (look at the
inode numbers before and after to verify, e.g. with "ls -li").
| [reply] [d/l] [select] |
|
It's not entierly clear to me what you are asking, but take a look at Tie::File, it might be what you are looking for.
| [reply] |
Re: read from a file and write into the same file
by manimarank (Novice) on Mar 03, 2008 at 10:48 UTC
|
Tie::File module is useful for modifying the exist file.
| [reply] |
Re: read from a file and write into the same file
by goibhniu (Hermit) on Mar 03, 2008 at 19:49 UTC
|
I think OP's problems were sufficiently pointed out. I was wondering if lexical file handles (open my $fh vs. open FILE) might be useful. What I found was that I successfully separated the input filehandle pointer from the output filehandle pointer, but the input filehandle stopped at the original eof instead of moving on through the new file contents. Could some wiser monks explain that to me?
C:\chas_sandbox>for %f in (a b c d) Do echo %f>>alpha.txt
C:\chas_sandbox>echo a 1>>alpha.txt
C:\chas_sandbox>echo b 1>>alpha.txt
C:\chas_sandbox>echo c 1>>alpha.txt
C:\chas_sandbox>echo d 1>>alpha.txt
C:\chas_sandbox>perl -le "open my $fh_in, '<', 'alpha.txt'; open my $f
+h_out, '>>
', 'alpha.txt';while (<$fh_in>) {chomp;print $fh_out chr(ord($_)+4); l
+ast if $_
eq 'v'}"
C:\chas_sandbox>type alpha.txt
a
b
c
d
e
f
g
h
#my sig used to say 'I humbly seek wisdom. '. Now it says:
use strict;
use warnings;
I humbly seek wisdom.
| [reply] [d/l] [select] |
|
...but the input filehandle stopped at the original eof
Presumably just the usual Suffering from Buffering.
Adding $fh_out->autoflush(1); (after having opened the output file) should make things behave as you
expect (fill the file with letters up to 'z'). You also need to
load IO::Handle for the autoflush method to be available
— i.e. -MIO::Handle if you want to stick with your one-liner :)
BTW, there is nothing special with lexical filehandles in this
regard, the piece of code would work just as well with normal
filehandles like IN, OUT.
| [reply] [d/l] [select] |