Schrift
[thread]7866[/thread]

Array ist nicht Array?!?: Was ist eigentlich ein Array in Perl?

Leser: 1


<< |< 1 2 3 >| >> 24 Einträge, 3 Seiten
highlander
 2006-04-07 17:02
#64535 #64535
User since
2006-04-07
5 Artikel
BenutzerIn
[default_avatar]
Hallo @all,

das ist mein erster Beitrag in diesem Forum und uberhaupt zum Thema Perl!

Hier ist mein Problem:

Ich wollte eine Datei zeichenweise (byteweise) auslesen:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
my @array;

sub readfile($){
open(DATEI, $_[0]);
my @Zeilen = <DATEI>;
close(DATEI);

my $length;
foreach my $zeile (@Zeilen){
$length = length $zeile;
for (my $i=0; $i<$length; $i++){
push(@array, substrg($zeile, $i, 1));
}
}
}



so weit so gut es funktioniert einwandfrei.

Wenn ich aber eine Groesere Datei nehme (z.B. 5MB)
dann wird mein swap-Speicher (500MB) voll :-(

dann habe ich gelesen dass Array in Perl das gleiche sind wie eine verketete Listen ist. Also um ein Array mit 5 Milllionen Zeichen zu erzeugen braucht man mehr als 700 MB Arbeitsspeicher: Ist es wahr?



ich habe das jetzt alles mit strings gelöst
Code: (dl )
my $Zeichen = read(DATEI);



Meine Frage ist: Gibt es ein Modul , der erlaubt echte Array zu erzeugen?


Gruss Vaceslav
Crian
 2006-04-07 17:11
#64536 #64536
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
Was verstehst du unter einem echten Array?

Edit: Herzlich willkommen :-)\n\n

<!--EDIT|Crian|1144415516-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
highlander
 2006-04-07 17:22
#64537 #64537
User since
2006-04-07
5 Artikel
BenutzerIn
[default_avatar]
[quote=Crian,07.04.2006, 15:11]Was verstehst du unter einem echten Array?[/quote]
Ein Array ist ein Stack in Speicher.

Ein Array soll folgendermassen aufgebaut werden:

Adresse Wert
0x5000 wert1
0x5001 wert2
0x5002 wert3
0x5003 wert4
0x6000 wert..n


Die Adresse 0x5000 ist die start-Adresse von Array und die Adresse 0x6000 End-Adresse von Array

Wenn ich jetzt auf 500.te Element zugreifen will dann kann ich direkt auf adresse 0x5500 zugreifen.

Bei einer Liste muss ich alle erste 500 elementen durchlaufen und nur dann kann ich auf 500.ste element zugreifen.
Crian
 2006-04-07 17:54
#64538 #64538
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
Das ist C-Denke bzw. ein C-Array :-)

Sei froh, dass man hier Perl-Arrays hat.
Nicht umsonst gibts in der STL Vector ...

Wenn du auf Element 500 zugreifen willst, kannst du das einfach mit $array[499] tun, da musst du nichts durchlaufen.\n\n

<!--EDIT|Crian|1144418182-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
lichtkind
 2006-04-07 18:02
#64539 #64539
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
du sagtest byteweise, willst du datei binär auslesen?

und um speicher zu sparen kannst du doch die datei in verdaulichen happen lesen einfach perldoc -f read lesen

dann weiter
Code: (dl )
1
2
3
for (my $i=0; $i<$length; $i++){
push(@array, substrg($zeile, $i, 1));
}

das geht in perl so
Code: (dl )
1
2
3
for my $i (0..$length-1){
push(@array, substrg($zeile, $i, 1));
}

dann gibt es keinen befehl substrg das heisst substr ausserdem sag lieber was du erreichen willst hab das gefühl du hast ihr sehr grundlegenden irrtum drin
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
highlander
 2006-04-07 19:05
#64540 #64540
User since
2006-04-07
5 Artikel
BenutzerIn
[default_avatar]
Quote

Wenn du auf Element 500 zugreifen willst, kannst du das einfach mit $array[499] tun, da musst du nichts durchlaufen.


Es gibt kein Unterschied zwieschen Arrays und Listen in Perl
Wenn du @array[499] schreibst dann durchlauft er (PERL) von 0->1->2->......->499

Obwohl ich kann mich irren. Ich bin doch nur ein neuling in Perl

Quote
sag lieber was du erreichen willst hab das gefühl du hast ihr sehr grundlegenden irrtum drin


Ich will die Datei (irgendeine) verschlüsseln.
Dafür muss ich auf jeden einzelnen Byte zugreifen.
Ich poste in Paar Stunden mein Quell-Code (bin jetzt nicht zu Hause)
Crian
 2006-04-07 19:08
#64541 #64541
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
Nein, das Array muss nicht durchlaufen werden, der Zugriff erfolgt in O(1).

Warum liest du dann nicht einfach Byte für Byte ein und schreibst diese verschlüsselt raus, du brauchst doch gar nicht alles einzulesen? (Naja, oder Stückweise, je nach Verschlüsselung.)

Eventuell hilft dir tie weiter?
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
lichtkind
 2006-04-07 20:50
#64542 #64542
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
für veschlüsselung kann man auch mehr auif einmal machen schau dir mal pack an und dafür brauchst du auch kein array anlegen denn so wie du es liest kannst dus gleich wieder in die nächste output datei schreiben brauchst also nur eine einfache variable. wenn du allerdings ernsthaft verschlüsseln willst schau mal ins cpan für blowfish etc.
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
highlander
 2006-04-07 21:50
#64543 #64543
User since
2006-04-07
5 Artikel
BenutzerIn
[default_avatar]
Quote
wenn du allerdings ernsthaft verschlüsseln willst schau mal ins cpan für blowfish etc.


Oh ne ne. Ich mach ganz leichte Verschlüsselung, die sieht so aus:
for (i=0;i<AnzahlZeichen;i++){
Zeichen[i] = Zeichen[i] xor NextPseudoRandomZeichen();
}

hier ist CODE:

Code: (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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/perl -w
use strict;
use warnings;

# Array mit Zeichen, die als Password genutzt werden
my @pass;
# Position in der Liste @pass
my $pass_pos = 0;

my $File;
my $CryptString;

my $StartTime;
my $StopTime;
my $Time;


#=== FUNCTION ================================================================
# NAME: readpass
# PURPOSE: ????
# DESCRIPTION: Liest eine Datei aus und benutzt sie als Password
# PARAMETERS: 1. Dateiname
# RETURNS: void
#===============================================================================
sub readpass($){
print "\nRead pass";
$StartTime = time;
my @Zeilen;
if ( -e $_[0]){
open(DATEI,$_[0]);
@Zeilen = <DATEI>;
close(DATEI);
}else{
print "\n\tDatei existiert nicht!! Dateiname wird als Passsword benutzt: $_[0]\n";
$Zeilen[0] = $_[0];
}

splice(@pass,0);
$pass_pos = 0;
foreach my $zeile (@Zeilen){
while (length $zeile > 0){
unshift(@pass, chop($zeile));
}
}
$StopTime = time;
print "\n\ttime: ".($StopTime - $StartTime);
$Time += $StopTime - $StartTime;
}
#=== FUNCTION ================================================================
# NAME: pass_getnext
# PURPOSE: ????
# DESCRIPTION: Liefert einen Pseudo-Random Zeichen zurück
# PARAMETERS: void
# RETURNS: Pseudo-Random Zeichen
#===============================================================================
sub pass_getnext(){
if ($pass_pos >= @pass){
$pass_pos = 0;
}
return ($pass[$pass_pos++]);
}
#=== FUNCTION ================================================================
# NAME: readfile
# PURPOSE: ????
# DESCRIPTION: Liest eine Datei aus und Speicher sie in Variable $File
# PARAMETERS: Dateiname
# RETURNS: void
#===============================================================================
sub readfile($){
print "\nRead file";
if (! -e $_[0]){
print "\n\tOriginal Datei ($_[0]) existiert nicht. Abbruch!\n";
exit;
}
$StartTime = time;
my $AnzahlBytes = -s $_[0];
open(DATEI,$_[0]) || die "Datei konnte nicht geoffnet werden: ".$_[0]."\n";
my $AnzahlZeichen = read(DATEI, $File, $AnzahlBytes);
close(DATEI);
$File = reverse($File);
$StopTime = time;
print "\n\ttime: ".($StopTime - $StartTime);
$Time += $StopTime - $StartTime;
}
#=== FUNCTION ================================================================
# NAME: cryptfile
# PURPOSE: ????
# DESCRIPTION: Verschlüsselt einen String ($File) und speichern es in $CryptString
# PARAMETERS: void
# RETURNS: void
#===============================================================================
sub cryptfile(){
print "\nCryptfile";
$StartTime = time;
# Position von Pseudo-Generator auf null setzen
$pass_pos = 0;
$CryptString = "";
my $rand;
while (length $File > 0){
$rand = pass_getnext();
$CryptString .= (chop($File) ^ $rand);
}
$StopTime = time;
print "\n\ttime: ".($StopTime - $StartTime);
$Time += $StopTime - $StartTime;
}
#=== FUNCTION ================================================================
# NAME: writefile
# PURPOSE: ????
# DESCRIPTION: Schreibt den String $CryptString in eine angegebene Datei
# PARAMETERS: Dateiname
# RETURNS: void
#===============================================================================
sub writefile($){
print "\nWrite file";
$StartTime = time;
open(DATEI,">".$_[0]);
print DATEI $CryptString;
close(DATEI);
$StopTime = time;
print "\n\ttime: ".($StopTime - $StartTime);
$Time += $StopTime - $StartTime;
}



#---------------------------------------------------------------------------
# Main-Function
#---------------------------------------------------------------------------
if (@ARGV != 3){
print "\nZu wenig Parameter!!\n";
print "\tParameter 1: Original Datei\n";
print "\tParameter 2: Password oder Dateiname mit Password\n";
print "\tParameter 3: Name für schifrierte Datei\n";
exit;
}
readpass($ARGV[1]);
readfile($ARGV[0]);
cryptfile();
writefile($ARGV[2]);

print "\nGesamtzeit: ".$Time;


Die Verschlüsselung funktioniert gut, das einzige was mich nicht gefällt ist die Ausführungszeit.

Bei einer Datei ,die 50 MB gross ist, dauert die Verschlüsselung 10-11 sek, das Auslesen und Speichern liegt unter einer Sekunde.

Das gleiche Algorithmus geschrieben in C++ braucht für 100 MB Datei nur eine Sekunde!!!!


Hat jemand eine Idde wie man das Beschleunigen kann?

Die Idee direkt beim Einlesen auch speichern, denke ich wird langsamer --> Festplattenzugriffzeit.



Gruss Vaceslav
lichtkind
 2006-04-07 22:10
#64544 #64544
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
äh zum stoppen der gebrauchten zeit kannst auch

use Benchmark; verwenden:
Code: (dl )
1
2
3
use Benchmark qw(:all);
my $t0 = new Benchmark;
print "xy brauchte :", Benchmark::timestr( Benchmark::timediff( new Benchmark, $t0 ) ), "\n";

warum benutzt du eigentlich nicht die lürzere for schleife

und ich glaube auch nicht das du wesentlich schneller bist wenn du zuerst alles einlesen willst und dann wieder alles schreiben willst, die meiste zeit praucht wirklich perl und wenn es keine dolle verschlüsselung sein wird schau dir wirklich pack an es ist wirklich geschwindigkeitsoptimiert oder du nimmst xor mit einem grösseren schlüssel.
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
<< |< 1 2 3 >| >> 24 Einträge, 3 Seiten



View all threads created 2006-04-07 17:02.