Thread Zeile x _schnell_ aus riesigem file raussuchen ? (19 answers)
Opened by Student87 at 2013-02-19 12:50

topeg
 2013-02-19 14:11
#165892 #165892
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich gehe nun von folgenden Voraussetzungen aus:
Es immer ein Zeichen+"\n" pro Zeile. Der Zeilenumbuch ist "\x0A" oder "\x0D\x0A" Das Zeichen sind reines ASCII und damit immer 1Byte lang. Du weißt in welcher Zeile sich das Zeichen befindet das du suchst.

Das als Voraussetzung.

Es gibt die Funktion seek die erlaubt es in einer geöffneten Datei zu "springen". Es wird der Pointer im Filehandle damit gesetzt. Aber das geht nur Byte weise. Mann kann nicht sagen "geh zu Zeile" da es für das Filehandle keine Zeile gibt. Das Macht Perl auf einer anderen Ebene.
Also seek kann nur die Byteposition in der Datei setzen.

Um es nutzen zu können muss du die Zeile, in die Byteposition umrechnen. Darum habe ich auch diese Annahmen am Anfang gemacht.

Wenn meine Annahme stimmt besteht eine Zeile immer aus zwei, oder wenn das Zeilenende "\r\n" ("\x0D\x0A") ist, aus drei Byte.

Der Code könnte so aussehen:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl
use strict;
use warnings;

# 1 -> Zeile 1
# 2 -> Zeile 2
# ...
my $position=100; # -> Zeile 100
my $file='test.dat';

my $bytepos=($position-1)*2; # *3 wenn \r\n

open(my $fh, '<', $file) or die("ERROR open $file ($!)\n");
seek($fh,$bytepos,0); # vom Anfang der Datei $bytepos Bytes weit gehen.
chomp(my $data=<$fh>);
close($fh);

print "$data\n";


Noch schneller geht es mit read Da ist die verwenung aber ungewohnt, da es eine direkt Umsetzung einer Systemfunktion ist.
Bei read kann man auch einen Offset mit angeben. Dass ist dann wie ein eingebautes seek. Aber das geht immer von der Aktuellen Position des Pointers in der Datei aus. In deinem Fall kannst du dir das seek dadurch sparen und read direkt nutzen:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl
use strict;
use warnings;

# 1 -> Zeile 1
# 2 -> Zeile 2
# ...
my $position=100; # -> Zeile 100
my $file='test.dat';

my $bytepos=($position-1)*2; # *3 wenn \r\n

open(my $fh, '<', $file) or die("ERROR open $file ($!)\n");
my $data='';
read($fh,$data,1,$bytepos);
close($fh);

print "$data\n";


Also schneller kommst du nicht an deinen Wert. Das funktioniert aber nur wenn jede Zeile die gleich Anzahl von Zeichen (Byte) hat!

View full thread Zeile x _schnell_ aus riesigem file raussuchen ?