Schrift
[thread]11666[/thread]

Text in Datei einfügen, nicht überschreiben

Leser: 2


<< >> 9 Einträge, 1 Seite
rommi
 2008-04-19 23:05
#108562 #108562
User since
2005-03-03
54 Artikel
BenutzerIn
[default_avatar]
Hallo Zusammen!

Ich will mit Perl einen Text in eine Text-Datei mit Inhalt einfügen. Ich will diesen Text zum Beispiel an Position 500 einfügen. Ich will aber nicht dass das was dort steht gelöscht wird, sondern dass es nach hinten verschoben wird. Ich habe versucht:

open (DATA,"+<file.txt");
seek DATA, 500,0;
print DATA " eingefügter Text ";
close(DATA);

aber es überschreibt das was an Position 500 steht mit " eingefügter Text "; Ich will aber das dazwischen eingefügt wird und der nachfolgende Text nach
"hinten" gerückt wird (wie bei einem Editor z.B. Notepad).

Gruss
rommi
pktm
 2008-04-19 23:54
#108563 #108563
User since
2003-08-07
2921 Artikel
BenutzerIn
[Homepage]
user image
Hallo!

Erzeuge ein Array.
Lies die Datei zeilenweise aus und stecke jede Zeile in das Array.
Wenn du an der gewünschten Position angekommen bist: füge deinen Inhalt ein.
Wenn du das getan hast füge auch die Restlichen Zeilen der Datei in das Array ein.
Überschreibe die Datei mit dem Inhalt des Arrays.

Damit bist du auf der sicheren Seite. Mit seek stellst du dir gerne mal selbst ein Bein.

Grüße, pktm
http://www.intergastro-service.de (mein erstes CMS :) )
topeg
 2008-04-20 14:33
#108572 #108572
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Wenn du schon seek nutzen willst musst du es so machen:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/perl

use strict;
use warnings;

my $file='test.txt';
my $line=30;
my $newdata=<<EOF;
neue zeile 1
neue zeile 2
neue zeile 3
neue zeile 4
neue zeile 5
neue zeile 6
neue zeile 7
neue zeile 8
neue zeile 9
EOF

{
 open(my $data, '+<', $file) or die "konnte $file nicht öffnen ($!)\n";

 #Zeile $line finden und Zeilenposition merken
 <$data> for(1..$line);
 my $pos=tell($data);

 #rest in ein String packen
 local $/=undef;
 my $rest=<$data>;
 
 # zur gemerkten Position gehen und neue Datan einfügen
 seek($data,$pos,0);
 print $data $newdata.$rest;

 close($data);
}

"seek" verlangt nicht die Position in Zeilen, sondern in Byte. Das kannst du nur mit "tell" zuverlässig ermitteln.
So etwas lohnt sich nur, wenn man wirklich große Dateien hat (mehrere MB). Ansonsten solltest du es machen machen wie pktm vorgeschlagen hat oder so:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/perl

use strict;
use warnings;

my $file='test.txt';
my $line=30;
my $newdata=<<EOF;
neue zeile 1
neue zeile 2
neue zeile 3
neue zeile 4
neue zeile 5
neue zeile 6
neue zeile 7
neue zeile 8
neue zeile 9
EOF

{
 open(my $data, '+<', $file) or die "konnte $file nicht öffnen ($!)\n";

 #alles vor der Einfügeposition merken
 my $vor='';
 ($vor.=<$data>)for(1..$line);

 #rest in ein String packen
 local $/=undef;
 my $rest=<$data>;
 
 # zum Anfang gehen und Daten schreiben
 seek($data,0,0);
 print $data $vor.$newdata.$rest;

 close($data);
}


p.s.: Richtig kompliziert wird es, wenn du selbst die Daten nach der Einfügestelle nicht speichern willst... :)
p.p.s.: Das sähe dann so aus:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/perl

use strict;
use warnings;

my $file='test.txt';
my $line=30;
my $newdata=<<EOF;
neue zeile 1
neue zeile 2
neue zeile 3
neue zeile 4
neue zeile 5
neue zeile 6
neue zeile 7
neue zeile 8
neue zeile 9
EOF

{
 open(my $data, '+<', $file) or die "konnte $file nicht öffnen ($!)\n";

 #Zeile $line finden und Zeilenposition merken
 <$data> for(1..$line);
 my $pos=tell($data);

 #rest in um die länge der Zeichen, die eingefügt werden sollen, verschieben
 my $length=length($newdata);
 seek($data,0,2);
 my $temppos=tell($data);
 print $data " "x$length;
 while($temppos>$pos)
 {
  $temppos--;
  seek($data,$temppos,0);
  read($data, my $z,1);
  seek($data,$temppos+$length,0);
  print $data $z;
 }

 # zur gemerkten Position gehen und neue Datan einfügen
 seek($data,$pos,0);
 print $data $newdata;

 close($data);
}
sid burn
 2008-04-20 16:24
#108579 #108579
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Eine weitere Möglichkeit wäre wenn du die Datei als einem String einlist und einfach einen substr machst und wieder neu Speicherst.

ungetestet:
Code: (dl )
1
2
3
4
5
6
7
8
9
open my $fh, '<:binary', $filename  or die $!;
my $text = do { local $/ = undef; <$fh> };
close $fh or die $!;

substr $text, 500, 0, 'eingefügter text';

open my $fh, '>:binary', $filename or die $!;
print {$fh} $text or die $!;
close $fh or die $!;
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
Gast Gast
 2008-04-20 20:09
#108590 #108590
Das würde funktionieren, wenn nach 500 Byte der Text eingefügt werden soll. Er soll aber ab der 500sten Zeile eingefügt werden.
Linuxer
 2008-04-20 22:28
#108599 #108599
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Gast+2008-04-20 18:09:17--
Er soll aber ab der 500sten Zeile eingefügt werden.


Das geht leider nicht aus der originalen Anfrage hervor.

CPAN:Tie::File könnte auch interessant für das beschriebene Problem sein.
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
pktm
 2008-04-20 23:23
#108604 #108604
User since
2003-08-07
2921 Artikel
BenutzerIn
[Homepage]
user image
Nimm meine Variante :D
http://www.intergastro-service.de (mein erstes CMS :) )
rommi
 2008-04-22 14:18
#108709 #108709
User since
2005-03-03
54 Artikel
BenutzerIn
[default_avatar]
Hallo Freunde der Sonne,

scheint hierfür keine "kurze" Lösung zu geben ausser den von pktm und
sid burn beschriebenen Lösungen. Sorry, mit Position meinte ich Byte also
Position 500 (Cursor) ist dann Byte 500 vom Dateianfang gerechnet.

Also ne kurze Lösung wäre eben (wenns funzen würde lol ) springe
mit seek an die Position, füge ein, fühle dich wohl und gehe nicht über Array oder substr ;-)

Vielen Dank für die Beiträge!
Gruss
rommi
murphy
 2008-04-22 20:54
#108749 #108749
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
rommi+2008-04-22 12:18:22--
[...]
Also ne kurze Lösung wäre eben (wenns funzen würde lol ) springe
mit seek an die Position, füge ein, fühle dich wohl und gehe nicht über Array oder substr ;-)
[...]


Das Problem ist halt, dass das Dateisystem nichts in eine Datei einfügen kann, sondern nur überschreiben oder hinten anhängen. Ohne Daten umzukopieren kommt man also nicht aus.

Für den Fall, dass man ständig in mehrere Gigabyte großen Dateien weit vorne etwas einfügen und deshalb riesige Datenmengen nach hinten verschieben muss, hat man eben Pech gehabt und sollte sich besser ein anderes Speicherformat überlegen ;-)
When C++ is your hammer, every problem looks like your thumb.
<< >> 9 Einträge, 1 Seite



View all threads created 2008-04-19 23:05.