[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 # IO::Zlib.pm 2 # 3 # Copyright (c) 1998-2004 Tom Hughes <tom@compton.nu>. 4 # All rights reserved. This program is free software; you can redistribute 5 # it and/or modify it under the same terms as Perl itself. 6 7 package IO::Zlib; 8 9 $VERSION = "1.07"; 10 11 =head1 NAME 12 13 IO::Zlib - IO:: style interface to L<Compress::Zlib> 14 15 =head1 SYNOPSIS 16 17 With any version of Perl 5 you can use the basic OO interface: 18 19 use IO::Zlib; 20 21 $fh = new IO::Zlib; 22 if ($fh->open("file.gz", "rb")) { 23 print <$fh>; 24 $fh->close; 25 } 26 27 $fh = IO::Zlib->new("file.gz", "wb9"); 28 if (defined $fh) { 29 print $fh "bar\n"; 30 $fh->close; 31 } 32 33 $fh = IO::Zlib->new("file.gz", "rb"); 34 if (defined $fh) { 35 print <$fh>; 36 undef $fh; # automatically closes the file 37 } 38 39 With Perl 5.004 you can also use the TIEHANDLE interface to access 40 compressed files just like ordinary files: 41 42 use IO::Zlib; 43 44 tie *FILE, 'IO::Zlib', "file.gz", "wb"; 45 print FILE "line 1\nline2\n"; 46 47 tie *FILE, 'IO::Zlib', "file.gz", "rb"; 48 while (<FILE>) { print "LINE: ", $_ }; 49 50 =head1 DESCRIPTION 51 52 C<IO::Zlib> provides an IO:: style interface to L<Compress::Zlib> and 53 hence to gzip/zlib compressed files. It provides many of the same methods 54 as the L<IO::Handle> interface. 55 56 Starting from IO::Zlib version 1.02, IO::Zlib can also use an 57 external F<gzip> command. The default behaviour is to try to use 58 an external F<gzip> if no C<Compress::Zlib> can be loaded, unless 59 explicitly disabled by 60 61 use IO::Zlib qw(:gzip_external 0); 62 63 If explicitly enabled by 64 65 use IO::Zlib qw(:gzip_external 1); 66 67 then the external F<gzip> is used B<instead> of C<Compress::Zlib>. 68 69 =head1 CONSTRUCTOR 70 71 =over 4 72 73 =item new ( [ARGS] ) 74 75 Creates an C<IO::Zlib> object. If it receives any parameters, they are 76 passed to the method C<open>; if the open fails, the object is destroyed. 77 Otherwise, it is returned to the caller. 78 79 =back 80 81 =head1 OBJECT METHODS 82 83 =over 4 84 85 =item open ( FILENAME, MODE ) 86 87 C<open> takes two arguments. The first is the name of the file to open 88 and the second is the open mode. The mode can be anything acceptable to 89 L<Compress::Zlib> and by extension anything acceptable to I<zlib> (that 90 basically means POSIX fopen() style mode strings plus an optional number 91 to indicate the compression level). 92 93 =item opened 94 95 Returns true if the object currently refers to a opened file. 96 97 =item close 98 99 Close the file associated with the object and disassociate 100 the file from the handle. 101 Done automatically on destroy. 102 103 =item getc 104 105 Return the next character from the file, or undef if none remain. 106 107 =item getline 108 109 Return the next line from the file, or undef on end of string. 110 Can safely be called in an array context. 111 Currently ignores $/ ($INPUT_RECORD_SEPARATOR or $RS when L<English> 112 is in use) and treats lines as delimited by "\n". 113 114 =item getlines 115 116 Get all remaining lines from the file. 117 It will croak() if accidentally called in a scalar context. 118 119 =item print ( ARGS... ) 120 121 Print ARGS to the file. 122 123 =item read ( BUF, NBYTES, [OFFSET] ) 124 125 Read some bytes from the file. 126 Returns the number of bytes actually read, 0 on end-of-file, undef on error. 127 128 =item eof 129 130 Returns true if the handle is currently positioned at end of file? 131 132 =item seek ( OFFSET, WHENCE ) 133 134 Seek to a given position in the stream. 135 Not yet supported. 136 137 =item tell 138 139 Return the current position in the stream, as a numeric offset. 140 Not yet supported. 141 142 =item setpos ( POS ) 143 144 Set the current position, using the opaque value returned by C<getpos()>. 145 Not yet supported. 146 147 =item getpos ( POS ) 148 149 Return the current position in the string, as an opaque object. 150 Not yet supported. 151 152 =back 153 154 =head1 USING THE EXTERNAL GZIP 155 156 If the external F<gzip> is used, the following C<open>s are used: 157 158 open(FH, "gzip -dc $filename |") # for read opens 159 open(FH, " | gzip > $filename") # for write opens 160 161 You can modify the 'commands' for example to hardwire 162 an absolute path by e.g. 163 164 use IO::Zlib ':gzip_read_open' => '/some/where/gunzip -c %s |'; 165 use IO::Zlib ':gzip_write_open' => '| /some/where/gzip.exe > %s'; 166 167 The C<%s> is expanded to be the filename (C<sprintf> is used, so be 168 careful to escape any other C<%> signs). The 'commands' are checked 169 for sanity - they must contain the C<%s>, and the read open must end 170 with the pipe sign, and the write open must begin with the pipe sign. 171 172 =head1 CLASS METHODS 173 174 =over 4 175 176 =item has_Compress_Zlib 177 178 Returns true if C<Compress::Zlib> is available. Note that this does 179 not mean that C<Compress::Zlib> is being used: see L</gzip_external> 180 and L<gzip_used>. 181 182 =item gzip_external 183 184 Undef if an external F<gzip> B<can> be used if C<Compress::Zlib> is 185 not available (see L</has_Compress_Zlib>), true if an external F<gzip> 186 is explicitly used, false if an external F<gzip> must not be used. 187 See L</gzip_used>. 188 189 =item gzip_used 190 191 True if an external F<gzip> is being used, false if not. 192 193 =item gzip_read_open 194 195 Return the 'command' being used for opening a file for reading using an 196 external F<gzip>. 197 198 =item gzip_write_open 199 200 Return the 'command' being used for opening a file for writing using an 201 external F<gzip>. 202 203 =back 204 205 =head1 DIAGNOSTICS 206 207 =over 4 208 209 =item IO::Zlib::getlines: must be called in list context 210 211 If you want read lines, you must read in list context. 212 213 =item IO::Zlib::gzopen_external: mode '...' is illegal 214 215 Use only modes 'rb' or 'wb' or /wb[1-9]/. 216 217 =item IO::Zlib::import: '...' is illegal 218 219 The known import symbols are the C<:gzip_external>, C<:gzip_read_open>, 220 and C<:gzip_write_open>. Anything else is not recognized. 221 222 =item IO::Zlib::import: ':gzip_external' requires an argument 223 224 The C<:gzip_external> requires one boolean argument. 225 226 =item IO::Zlib::import: 'gzip_read_open' requires an argument 227 228 The C<:gzip_external> requires one string argument. 229 230 =item IO::Zlib::import: 'gzip_read' '...' is illegal 231 232 The C<:gzip_read_open> argument must end with the pipe sign (|) 233 and have the C<%s> for the filename. See L</"USING THE EXTERNAL GZIP">. 234 235 =item IO::Zlib::import: 'gzip_write_open' requires an argument 236 237 The C<:gzip_external> requires one string argument. 238 239 =item IO::Zlib::import: 'gzip_write_open' '...' is illegal 240 241 The C<:gzip_write_open> argument must begin with the pipe sign (|) 242 and have the C<%s> for the filename. An output redirect (>) is also 243 often a good idea, depending on your operating system shell syntax. 244 See L</"USING THE EXTERNAL GZIP">. 245 246 =item IO::Zlib::import: no Compress::Zlib and no external gzip 247 248 Given that we failed to load C<Compress::Zlib> and that the use of 249 an external F<gzip> was disabled, IO::Zlib has not much chance of working. 250 251 =item IO::Zlib::open: needs a filename 252 253 No filename, no open. 254 255 =item IO::Zlib::READ: NBYTES must be specified 256 257 We must know how much to read. 258 259 =item IO::Zlib::WRITE: too long LENGTH 260 261 The LENGTH must be less than or equal to the buffer size. 262 263 =item IO::Zlib::WRITE: OFFSET is not supported 264 265 Offsets of gzipped streams are not supported. 266 267 =back 268 269 =head1 SEE ALSO 270 271 L<perlfunc>, 272 L<perlop/"I/O Operators">, 273 L<IO::Handle>, 274 L<Compress::Zlib> 275 276 =head1 HISTORY 277 278 Created by Tom Hughes E<lt>F<tom@compton.nu>E<gt>. 279 280 Support for external gzip added by Jarkko Hietaniemi E<lt>F<jhi@iki.fi>E<gt>. 281 282 =head1 COPYRIGHT 283 284 Copyright (c) 1998-2004 Tom Hughes E<lt>F<tom@compton.nu>E<gt>. 285 All rights reserved. This program is free software; you can redistribute 286 it and/or modify it under the same terms as Perl itself. 287 288 =cut 289 290 require 5.004; 291 292 use strict; 293 use vars qw($VERSION $AUTOLOAD @ISA); 294 295 use Carp; 296 use Fcntl qw(SEEK_SET); 297 298 my $has_Compress_Zlib; 299 my $aliased; 300 301 sub has_Compress_Zlib { 302 $has_Compress_Zlib; 303 } 304 305 BEGIN { 306 eval { require Compress::Zlib }; 307 $has_Compress_Zlib = $@ ? 0 : 1; 308 } 309 310 use Symbol; 311 use Tie::Handle; 312 313 # These might use some $^O logic. 314 my $gzip_read_open = "gzip -dc %s |"; 315 my $gzip_write_open = "| gzip > %s"; 316 317 my $gzip_external; 318 my $gzip_used; 319 320 sub gzip_read_open { 321 $gzip_read_open; 322 } 323 324 sub gzip_write_open { 325 $gzip_write_open; 326 } 327 328 sub gzip_external { 329 $gzip_external; 330 } 331 332 sub gzip_used { 333 $gzip_used; 334 } 335 336 sub can_gunzip { 337 $has_Compress_Zlib || $gzip_external; 338 } 339 340 sub _import { 341 my $import = shift; 342 while (@_) { 343 if ($_[0] eq ':gzip_external') { 344 shift; 345 if (@_) { 346 $gzip_external = shift; 347 } else { 348 croak "$import: ':gzip_external' requires an argument"; 349 } 350 } 351 elsif ($_[0] eq ':gzip_read_open') { 352 shift; 353 if (@_) { 354 $gzip_read_open = shift; 355 croak "$import: ':gzip_read_open' '$gzip_read_open' is illegal" 356 unless $gzip_read_open =~ /^.+%s.+\|\s*$/; 357 } else { 358 croak "$import: ':gzip_read_open' requires an argument"; 359 } 360 } 361 elsif ($_[0] eq ':gzip_write_open') { 362 shift; 363 if (@_) { 364 $gzip_write_open = shift; 365 croak "$import: ':gzip_write_open' '$gzip_read_open' is illegal" 366 unless $gzip_write_open =~ /^\s*\|.+%s.*$/; 367 } else { 368 croak "$import: ':gzip_write_open' requires an argument"; 369 } 370 } 371 else { 372 last; 373 } 374 } 375 return @_; 376 } 377 378 sub _alias { 379 my $import = shift; 380 if ((!$has_Compress_Zlib && !defined $gzip_external) || $gzip_external) { 381 # The undef *gzopen is really needed only during 382 # testing where we eval several 'use IO::Zlib's. 383 undef *gzopen; 384 *gzopen = \&gzopen_external; 385 *IO::Handle::gzread = \&gzread_external; 386 *IO::Handle::gzwrite = \&gzwrite_external; 387 *IO::Handle::gzreadline = \&gzreadline_external; 388 *IO::Handle::gzeof = \&gzeof_external; 389 *IO::Handle::gzclose = \&gzclose_external; 390 $gzip_used = 1; 391 } else { 392 croak "$import: no Compress::Zlib and no external gzip" 393 unless $has_Compress_Zlib; 394 *gzopen = \&Compress::Zlib::gzopen; 395 *gzread = \&Compress::Zlib::gzread; 396 *gzwrite = \&Compress::Zlib::gzwrite; 397 *gzreadline = \&Compress::Zlib::gzreadline; 398 *gzeof = \&Compress::Zlib::gzeof; 399 } 400 $aliased = 1; 401 } 402 403 sub import { 404 shift; 405 my $import = "IO::Zlib::import"; 406 if (@_) { 407 if (_import($import, @_)) { 408 croak "$import: '@_' is illegal"; 409 } 410 } 411 _alias($import); 412 } 413 414 @ISA = qw(Tie::Handle); 415 416 sub TIEHANDLE 417 { 418 my $class = shift; 419 my @args = @_; 420 421 my $self = bless {}, $class; 422 423 return @args ? $self->OPEN(@args) : $self; 424 } 425 426 sub DESTROY 427 { 428 } 429 430 sub OPEN 431 { 432 my $self = shift; 433 my $filename = shift; 434 my $mode = shift; 435 436 croak "IO::Zlib::open: needs a filename" unless defined($filename); 437 438 $self->{'file'} = gzopen($filename,$mode); 439 440 return defined($self->{'file'}) ? $self : undef; 441 } 442 443 sub CLOSE 444 { 445 my $self = shift; 446 447 return undef unless defined($self->{'file'}); 448 449 my $status = $self->{'file'}->gzclose(); 450 451 delete $self->{'file'}; 452 453 return ($status == 0) ? 1 : undef; 454 } 455 456 sub READ 457 { 458 my $self = shift; 459 my $bufref = \$_[0]; 460 my $nbytes = $_[1]; 461 my $offset = $_[2] || 0; 462 463 croak "IO::Zlib::READ: NBYTES must be specified" unless defined($nbytes); 464 465 $$bufref = "" unless defined($$bufref); 466 467 my $bytesread = $self->{'file'}->gzread(substr($$bufref,$offset),$nbytes); 468 469 return undef if $bytesread < 0; 470 471 return $bytesread; 472 } 473 474 sub READLINE 475 { 476 my $self = shift; 477 478 my $line; 479 480 return () if $self->{'file'}->gzreadline($line) <= 0; 481 482 return $line unless wantarray; 483 484 my @lines = $line; 485 486 while ($self->{'file'}->gzreadline($line) > 0) 487 { 488 push @lines, $line; 489 } 490 491 return @lines; 492 } 493 494 sub WRITE 495 { 496 my $self = shift; 497 my $buf = shift; 498 my $length = shift; 499 my $offset = shift; 500 501 croak "IO::Zlib::WRITE: too long LENGTH" unless $offset + $length <= length($buf); 502 503 return $self->{'file'}->gzwrite(substr($buf,$offset,$length)); 504 } 505 506 sub EOF 507 { 508 my $self = shift; 509 510 return $self->{'file'}->gzeof(); 511 } 512 513 sub FILENO 514 { 515 return undef; 516 } 517 518 sub new 519 { 520 my $class = shift; 521 my @args = @_; 522 523 _alias("new", @_) unless $aliased; # Some call new IO::Zlib directly... 524 525 my $self = gensym(); 526 527 tie *{$self}, $class, @args; 528 529 return tied(${$self}) ? bless $self, $class : undef; 530 } 531 532 sub getline 533 { 534 my $self = shift; 535 536 return scalar tied(*{$self})->READLINE(); 537 } 538 539 sub getlines 540 { 541 my $self = shift; 542 543 croak "IO::Zlib::getlines: must be called in list context" 544 unless wantarray; 545 546 return tied(*{$self})->READLINE(); 547 } 548 549 sub opened 550 { 551 my $self = shift; 552 553 return defined tied(*{$self})->{'file'}; 554 } 555 556 sub AUTOLOAD 557 { 558 my $self = shift; 559 560 $AUTOLOAD =~ s/.*:://; 561 $AUTOLOAD =~ tr/a-z/A-Z/; 562 563 return tied(*{$self})->$AUTOLOAD(@_); 564 } 565 566 sub gzopen_external { 567 my ($filename, $mode) = @_; 568 require IO::Handle; 569 my $fh = IO::Handle->new(); 570 if ($mode =~ /r/) { 571 # Because someone will try to read ungzipped files 572 # with this we peek and verify the signature. Yes, 573 # this means that we open the file twice (if it is 574 # gzipped). 575 # Plenty of race conditions exist in this code, but 576 # the alternative would be to capture the stderr of 577 # gzip and parse it, which would be a portability nightmare. 578 if (-e $filename && open($fh, $filename)) { 579 binmode $fh; 580 my $sig; 581 my $rdb = read($fh, $sig, 2); 582 if ($rdb == 2 && $sig eq "\x1F\x8B") { 583 my $ropen = sprintf $gzip_read_open, $filename; 584 if (open($fh, $ropen)) { 585 binmode $fh; 586 return $fh; 587 } else { 588 return undef; 589 } 590 } 591 seek($fh, 0, SEEK_SET) or 592 die "IO::Zlib: open('$filename', 'r'): seek: $!"; 593 return $fh; 594 } else { 595 return undef; 596 } 597 } elsif ($mode =~ /w/) { 598 my $level = ''; 599 $level = "-$1" if $mode =~ /([1-9])/; 600 # To maximize portability we would need to open 601 # two filehandles here, one for "| gzip $level" 602 # and another for "> $filename", and then when 603 # writing copy bytes from the first to the second. 604 # We are using IO::Handle objects for now, however, 605 # and they can only contain one stream at a time. 606 my $wopen = sprintf $gzip_write_open, $filename; 607 if (open($fh, $wopen)) { 608 $fh->autoflush(1); 609 binmode $fh; 610 return $fh; 611 } else { 612 return undef; 613 } 614 } else { 615 croak "IO::Zlib::gzopen_external: mode '$mode' is illegal"; 616 } 617 return undef; 618 } 619 620 sub gzread_external { 621 # Use read() instead of syswrite() because people may 622 # mix reads and readlines, and we don't want to mess 623 # the stdio buffering. See also gzreadline_external() 624 # and gzwrite_external(). 625 my $nread = read($_[0], $_[1], @_ == 3 ? $_[2] : 4096); 626 defined $nread ? $nread : -1; 627 } 628 629 sub gzwrite_external { 630 # Using syswrite() is okay (cf. gzread_external()) 631 # since the bytes leave this process and buffering 632 # is therefore not an issue. 633 my $nwrote = syswrite($_[0], $_[1]); 634 defined $nwrote ? $nwrote : -1; 635 } 636 637 sub gzreadline_external { 638 # See the comment in gzread_external(). 639 $_[1] = readline($_[0]); 640 return defined $_[1] ? length($_[1]) : -1; 641 } 642 643 sub gzeof_external { 644 return eof($_[0]); 645 } 646 647 sub gzclose_external { 648 close($_[0]); 649 # I am not entirely certain why this is needed but it seems 650 # the above close() always fails (as if the stream would have 651 # been already closed - something to do with using external 652 # processes via pipes?) 653 return 0; 654 } 655 656 1;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |