2010-09-08 4 views
5

Ich versuche, in Datei bei N-ten Position zu schreiben. Ich habe es mit Beispiel unten versucht, aber es schreibt am Ende. Bitte helfen Sie dies zu erreichen.perl: Datei an der N-ten Position schreiben

#!/usr/bin/perl 

open(FILE,"+>>try.txt") 
or 
die ("Cant open file try.txt"); 

$POS=5; 

    seek(FILE,$POS,0); 

    print FILE "CP1"; 
+1

Haben Sie versucht, einen Modus zu verwenden, der nicht anfügt? wie zum Beispiel: open (meine $ fh, '<+', "try.txt") oder die $ !; (Dies ist auch eine "modernere" Verwendung von open(), siehe http://perldoc.perl.org/functions/open.html) –

+0

@ Øyvind Skaar Es ist "" <"<" <"<" <" '. –

+0

@chas richtig du bist .. –

Antwort

3

Sie öffnen die Datei im Lese-Schreib-Anfügemodus. Versuchen Sie, die Datei in Lese-Schreib-Modus öffnen:

my $file = "try.txt"; 
open my $fh, "+<", $file 
    or die "could not open $file: $!"; 

Beachten Sie auch, die Verwendung der drei Argument open, der lexikalische Dateihandles und $!.

#!/usr/bin/perl 

use strict; 
use warnings; 

#create an in-memory file 
my $fakefile = "1234567890\n"; 
open my $fh, "+<", \$fakefile 
    or die "Cant open file: $!"; 

my $offset = 5; 

seek $fh, $offset, 0 
    or die "could not seek: $!"; 

print $fh "CP1"; 

print $fakefile; 

Der obige Code druckt:

12345CP190 
+0

Hi Chas kann es möglich sein, das Zeichen an N-Stelle anhängen, dh das N-te Zeichen zu N + 1 N + 1 bis N + 2 und so weiter – vrbilgi

+0

@ user430294: Nicht wirklich. Sie müssen den Inhalt tatsächlich nach N lesen und ihn dann an anderer Stelle wieder schreiben. –

+0

@ user430294 Nein, Dateien funktionieren nicht so. –

2

diese

use strict; 
use warnings; 

open(my $fh, '+<', 'foo.txt') or die $!; 

seek($fh, 3, 0); 

print $fh "WH00t?"; 

ist dies auch eine "moderne" Verwendung von open() funktioniert für mich, sehen http://perldoc.perl.org/functions/open.html

Die Datei wird geschlossen, wenn $ fh den Gültigkeitsbereich verlässt.

+0

@Skaar Ihre Lösung funktioniert gut. Aber es ersetzt das in der Datei vorhandene Zeichen. Ich möchte den Inhalt an der N-ten Position anhängen, dh das N-te Zeichen an N + 1 N + 1 bis N + 2 und so weiter verschieben. – vrbilgi

+0

hm .. Sie könnten es lesen und dann wieder ausschreiben .. vielleicht hat jemand eine bessere Lösung .. Aber ich denke, "Append-Modus" (>>) bedeutet nur, dass es beginnt, am Ende der Datei zu schreiben, so dass ist nicht was du willst. –

4

Wenn ich Sie richtig verstehe, wenn der Inhalt der Datei

123456789

sind, wollen Sie, dass

1234CP157689

Sie können, dass die Verwendung zu open (unabhängig Sprache der Programmierung) geliefert Modi nicht erreichen zu

ändern.

Sie müssen die Quelldatei und eine andere temporäre Datei öffnen (siehe File::Temp. Lesen von der Quelle bis zur Einfügemarke und den Inhalt in die temporäre Datei schreiben, schreiben, was Sie einfügen möchten, schreiben Sie dann den Rest der Quelldatei in die temporäre Datei, schließen Sie die Quelle und rename die temporäre auf die Quelle.

Wenn Sie dies mit seek tun werden, müssen beide Dateien im binär-Modus geöffnet werden.

Hier ist ein Beispiel unter Verwendung von Zeilenorientierter Eingabe- und Textmodus:

#!/usr/bin/perl 

use strict; use warnings; 
use File::Temp qw(:POSIX); 

my $source = 'test.test'; 
my $temp = tmpnam; 

open my $source_h, '<', $source 
    or die "Failed to open '$source': $!"; 

open my $temp_h, '>', $temp 
    or die "Failed to open '$temp' for writing: $!"; 

while (my $line = <$source_h>) { 
    if ($line =~ /^[0-9]+$/) { 
     $line = substr($line, 0, 5) . "CP1" . substr($line, 5); 
    } 
    print $temp_h $line; 
} 

close $temp_h 
    or die "Failed to close '$temp': $!"; 

close $source_h 
    or die "Failed to close '$source': $!"; 

rename $temp => $source 
    or die "Failed to rename '$temp' to '$source': $!"; 
2

"Einfügen" eines Strings in eine Funktion kann (meistens) an Ort und Stelle erfolgen. Sehen Sie die leicht benutzte eingebaute Funktion truncate.

open my $fh, '+<', $file or die $!; 
seek $fh, 5, 0; 
$/ = undef; 
$x = <$fh>; # read everything after the 5th byte into $x 
truncate $fh, 5; 
print $fh "CPI"; 
print $fh $x; 
close $fh; 
+0

+1 Ich mag das! Muss die Datei im Bin-Modus für die Windows-Plattform sein? – dawg

-1

Wenn Ihre Datei Zeile oder Datensatz ausgerichtet ist, können Sie Zeilen einfügen oder einzelne Linien leicht mit dem Kernmodul ändern Tie::File Dies wird die Datei als Array und Perl-String und Array-Manipulation behandelt werden, damit verwendet werden um die Datei im Speicher zu ändern. Mit dieser Methode können Sie mit großen Dateien arbeiten, die größer als Ihr RAM sind.Hier

ist ein Beispiel:

use strict; use warnings; 
use Tie::File; 

#create the default .txt file: 
open (my $out, '>', "nums.txt") or die $!; 
while(<DATA>) { print $out "$_"; } 
close $out or die $!; 

tie my @data, 'Tie::File', "nums.txt" or die $!; 

my $offset=5; 
my $insert="INSERTED"; 

#insert in a string: 
$data[0]=substr($data[0],0,$offset).$insert.substr($data[0],$offset) 
    if (length($data[0])>$offset); 

#insert a new array element that becomes a new file line:  
splice @data,$offset,0,join(':',split(//,$insert)); 

#insert vertically: 
$data[$_]=substr($data[$_],0,$offset) . 
      substr(lc $insert,$_,1) . 
      substr($data[$_],$offset) for (0..length($insert)); 

untie @data; #close the file too... 

__DATA__ 
123456789 
234567891 
345678912 
456789123 
567891234 
678912345 
789123456 
891234567 
912345678 

Output:

12345iINSERTED6789 
23456n7891 
34567s8912 
45678e9123 
56789r1234 
I:N:St:E:R:T:E:D 
67891e2345 
78912d3456 
891234567 
912345678 

Die Dateiänderungen mit Tie::File werden an Ort und Stelle hergestellt und wie das Array modifiziert wird. Sie könnten Tie::File nur in der ersten Zeile der Datei verwenden, um zu ändern und einzufügen, wie Sie angefordert haben. Sie können sleep zwischen den Array-Mods setzen und tail -n +0 -f auf die Datei verwenden und die Datei ändern sehen, wenn Sie es wünschen ...

Alternativ, wenn Sie Ihre Datei angemessene Größe ist und Sie wollen es wie Zeichen zu behandeln, können Sie das lesen gesamte Datei in den Speicher, führen Sie String-Operationen für die Daten aus und schreiben Sie die geänderten Daten dann wieder zurück. Bedenken Sie:

use strict; use warnings; 

#creat the default .txt file: 
open (my $out, '>', "nums.txt") or die $!; 
while(<DATA>) { print $out "$_"; } 
close $out or die $!; 

my $data; 
open (my $in, '<', "nums.txt") or die $!; 
{ local $/=undef; $data=<$in>; } 
close $in or die $!; 

my $offset=5; 
my $insert="INSERTED"; 

open (my $out, '>', "nums.txt") or die $!; 
print $out substr($data,0,$offset).$insert.substr($data,$offset); 
close $out or die $!; 

__DATA__ 
123456789 
2 
3 
4 
5 
6 
7 
8 
9 

Ausgang:

12345INSERTED6789 
2 
3 
4 
5 
6 
7 
8 
9 

Wenn Sie Dateien als Zeichen behandeln, hüte dich, dass unter Windows, Dateien im Textmodus ein \r\n für eine neue Zeile haben. Das sind zwei Zeichen, wenn sie im Binärmodus geöffnet werden.

+0

Warum die Zufallswahl? – dawg

Verwandte Themen