Schrift
[thread]9148[/thread]

substr(): Alternative gesucht



<< |< 1 2 >| >> 16 Einträge, 2 Seiten
bloonix
 2007-07-02 15:44
#78132 #78132
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Hallo Community,

ich suche eine Alternative zu substr() um einen binären String Byteweise
in einer Schleife zu verarbeiten. Was mir an substr() nicht gefällt ist,
dass der $string jedesmal an substr() übergeben wird, lieber wäre es
mir, wenn ich den String "irgendwohin gebe" und den String dann in
8 Byte Häppchen zurück bekomme. Gibt es eine andere Möglichkeit?
Hier mein Codebeispiel mit substr():

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
use strict;
use warnings;
use Storable;

package Parent;

sub run {
  my $pipe = shift;

  # der zu sendende String
  my $string  = 'Hello World!';
     $string  = Storable::nfreeze(\$string);
  my $length  = length($string);

  # maximale Bytes die geschrieben werden sollen
  my $maxbyt  = 8;
  my $offset  = 0;
  my $rest    = $length;
  my $sdsz    = $length < $maxbyt ? $length : $maxbyt;

  open my $fh, '>>', $pipe or die $!;

  while (my $chunk = substr($string, $offset, $sdsz)) {
     syswrite($fh, $chunk, $sdsz) == $sdsz or die;
     $rest -= $maxbyt;
     last unless $rest;
     $offset += $maxbyt;
     $sdsz = $rest if $rest < $maxbyt;
  }  

  close $fh;
}

package Child;

sub run {
  my $pipe   = shift;
  my $rdsz   = 8;
  my $string = ();

  open my $fh, '<', $pipe or die $!;

  while (my $byt = read($fh, my $chunk, $rdsz)) {
     die unless $byt == $rdsz;
     $string .= $chunk;
  }  

  close $fh;

  $string = Storable::thaw($string);
  print "\n<$$string>\n";
}

package main;

use POSIX qw/mkfifo/;

my $pipe = int(rand(999999));
mkfifo($pipe, 0600) or die;

if (fork) {
  Parent::run($pipe);
} else {
  Child::run($pipe);
unlink($pipe);
}


Gruss,
opi\n\n

<!--EDIT|opi|1183376728-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
pq
 2007-07-02 16:23
#78133 #78133
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
[quote=opi,02.07.2007, 13:44]Was mir an substr() nicht gefällt ist,
dass der $string jedesmal an substr() übergeben wird, lieber wäre es
mir, wenn ich den String "irgendwohin gebe" und den String dann in
8 Byte Häppchen zurück bekomme.[/quote]
wieso eigentlich?

my @chunks = $string =~ m/.{1,8}/gs;
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
moritz
 2007-07-02 16:40
#78134 #78134
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Für mich hört sich das nach einem Fall für unpack an, aber ich kenne mich damit zu wenig aus, um dir eine genaue Lösung sagen zu können.
bloonix
 2007-07-02 17:08
#78135 #78135
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=pq,02.07.2007, 14:23][quote=opi,02.07.2007, 13:44]Was mir an substr() nicht gefällt ist,
dass der $string jedesmal an substr() übergeben wird, lieber wäre es
mir, wenn ich den String "irgendwohin gebe" und den String dann in
8 Byte Häppchen zurück bekomme.[/quote]
wieso eigentlich?[/quote]
das versuche ich gerade rauszufinden :)

Man kann nicht unendlich viel von einem Filehandle mittels sysread()
oder syswrite() lesen bzw schreiben. Die empfohlene Größe kann mittels
stat($fh)[11] herausbekommen werden, oder aber man setzt die Größe
fix auf 16384 Bytes. Warum gerade soviel, versuche ich zu ergooglen.
Das ist wohl die maximale Buffersize... aber wovon... dunno. Ich suche
die Lösung :)

@morizt: unpack() oder pack() kann an dieser Stelle nicht gebraucht
werden. Der 3 Parameter von syswrite() ist das, was ich brauche (OFFSET).
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
sid burn
 2007-07-02 17:27
#78136 #78136
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Man kann nicht unendlich viel von einem Filehandle mittels sysread() oder syswrite() lesen bzw schreiben. Die empfohlene Größe kann mittels stat($fh)[11] herausbekommen werden, oder aber man setzt die Größe fix auf 16384 Bytes

Nur weil dort eine empfohlene Größe steht, heißt es ja nicht gleich das es das Maximum ist. Bei mir ist es übrigens "4096" Bytes, und keine 16Kib.

So wie es ausschaut ist die empfohlene Größe einfach die Blockgröße des Filesystems...

Quote
@morizt: unpack() oder pack() kann an dieser Stelle nicht gebraucht werden. Der 3 Parameter von syswrite() ist das, was ich brauche (OFFSET).

Deine Frage lautete doch ursprünglich wie du einen String in 8 Bytes Chunks zerlegen kannst. Wie kommst du den jetzt vom Lesen, zum schreiben (syswrite()) und von einem String zu einem Filehandle?

Und was heißt den dritten parameter von sywrite benötigst du? syswrite gibt doch nur einen Wert zurück. ;)

---------------

Ansonsten kenne ich mich mit unpack auch schlecht aus. Aber ein String in 8 Bytes Häpchen geht anscheind so: (Ich weiß aber nciht ob "a" unbedingt die richtige Wahl ist:

Code: (dl )
my @chunks = unpack '(a8)*', $string;
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
bloonix
 2007-07-02 18:15
#78137 #78137
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=sid burn,02.07.2007, 15:27]Nur weil dort eine empfohlene Größe steht, heißt es ja nicht gleich das es das Maximum ist. Bei mir ist es übrigens "4096" Bytes, und keine 16Kib.[/quote]
Wo habe ich denn was von maximaler Größe verlauten lassen?

[quote=sid burn,02.07.2007, 15:27]So wie es ausschaut ist die empfohlene Größe einfach die Blockgröße des Filesystems...[/quote]
Das ist nur bedingt richtig.

Code: (dl )
1
2
3
4
5
6
7
8
9
use IO::Socket::INET;

my $ipc = IO::Socket::INET->new(
  LocalAddr => 'localhost',
  Listen    => 1,
  Proto     => 'tcp',
);

print "SIZE: ", (stat($ipc))[11], "\n";


SIZE: 1024

[quote=sid burn,02.07.2007, 15:27]Deine Frage lautete doch ursprünglich wie du einen String in 8 Bytes Chunks zerlegen kannst. Wie kommst du den jetzt vom Lesen, zum schreiben (syswrite()) und von einem String zu einem Filehandle?[/quote]
Du bringst ja hier viel mehr durcheinander als ich! Ich habe von Anfang
an von syswrite() geschrieben, denn genau das ist es ja, was ich mit
den Chunks machen möchte! Stückchenweise irgendwo hin schreiben.

[quote=sid burn,02.07.2007, 15:27]Und was heißt den dritten parameter von sywrite benötigst du? syswrite gibt doch nur einen Wert zurück. ;)[/quote]
Du verwechselst wohl gerade return-Werte mit Parametern, die an eine
Funktion übergeben werden. ;) Meine Rede war von OFFSET, dem 4. - sorry
ich schrieb 3. - Parameter von syswrite(). Allerdings kann unpack()
tatsächlich das, was ich suche, das wusste ich nicht und der Antwort von
moritz zu wenig Aufmerksamkeit geschenkt. :) Mea culpa @moritz\n\n

<!--EDIT|opi|1183457815-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
pq
 2007-07-02 18:41
#78138 #78138
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
opi, komm mal wieder runter. deine frage war "ich suche eine Alternative zu substr() um einen
binären String Byteweise in einer Schleife zu verarbeiten."
wie du da auf syswrite kommst, ist erstmal ziemlich unklar.
im übrigen macht meine regex auch genau das, was eine entsprechende unpack-lösung macht.\n\n

<!--EDIT|pq|1183387846-->
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
shigetsu
 2007-07-02 19:06
#78139 #78139
User since
2007-04-22
16 Artikel
BenutzerIn
[Homepage] [default_avatar]
Im ungewissen, obs denn relevant sei:

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

use strict;
use warnings;

use Data::Dumper qw(Dumper);

my $vector = '123456789';
my $bits = unpack 'b*', $vector;
my @bits = split //, $bits;

my @bytes;
while (@bits) {
    #my $byte = pack 'b8', join '', splice(@bits, 0, 8); # 1-byte (ascii)
    #my $byte = join '', splice(@bits, 0, 8); # 8-bit (bits)
    #my $byte = join '', splice(@bits, 0, 64); # 64-bit (bits)
    push @bytes, $byte;
}

print Dumper \@bytes;      


#1
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
$VAR1 = [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'
];


#2
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
$VAR1 = [
'10001100',
'01001100',
'11001100',
'00101100',
'10101100',
'01101100',
'11101100',
'00011100',
'10011100'
];


#3
Code: (dl )
1
2
3
4
$VAR1 = [
'1000110001001100110011000010110010101100011011001110110000011100',
'10011100'
];
\n\n

<!--EDIT|shigetsu|1183389239-->
bloonix
 2007-07-02 19:17
#78140 #78140
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
danke shigetsu, dein 2. beispiel ist relevant
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
bloonix
 2007-07-02 19:35
#78141 #78141
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Kurze Erläuterung warum syswrite() + 16k + so weiter...

Aus irgendeinem Grund werden immer nur 16384 Bytes (16k) über das
Socket geschrieben und gelesen. Dieses Phenomän - wenn man es so
ausdrücken darf - habe ich allerdings nur bei IO::Socket::SSL festgestellt,
nicht aber bei IO::Socket::INET. Deshalb wollte ich auch bzw muss ich die
Daten in Chunks aufteilen. Mir war aber nicht ganz klar, wie ich das so
realisieren kann.

Nun habe ich es wie folgt hinbekommen (ohne unpack()):

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    my $buffer = 'x' x 100000000;
   my $length = length($buffer);
   my $offset = 0;
   my $i      = 0;

   my $client = $ipc->accept();
   warn "connect from: ", $client->peerhost, "\n";
   warn "print $length bytes to client\n";

   while ($length) {
     # syswrite() schreibt immer nur 16k bei IO::Socket::SSL
      my $written = syswrite($client, $buffer, $length, $offset);
      die "System write error: $!\n" unless defined $written;
      $length -= $written;
      $offset += $written;
      $i++;
   }  

   warn "Iterations: $i\n";


Iterations: 6104

Die unpack() Beispiele könnten aber von größerem Interesse sein, da ich
die Chunks direkt erhalte und nicht den gesamten $buffer jedesmal an
syswrite() übergeben muss.\n\n

<!--EDIT|opi|1183390659-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
<< |< 1 2 >| >> 16 Einträge, 2 Seiten



View all threads created 2007-07-02 15:44.