From aea17f4391d9d286d3b73649b1667aa41e3d0ca0 Mon Sep 17 00:00:00 2001
From: Alessandro Vullo <avullo@ebi.ac.uk>
Date: Tue, 2 Dec 2014 16:00:45 +0000
Subject: [PATCH] Work with bz2 files.

---
 modules/Bio/EnsEMBL/Utils/IO.pm | 65 +++++++++++++++++++++++++++++----
 1 file changed, 57 insertions(+), 8 deletions(-)

diff --git a/modules/Bio/EnsEMBL/Utils/IO.pm b/modules/Bio/EnsEMBL/Utils/IO.pm
index 32c9370450..5d9115cd1a 100644
--- a/modules/Bio/EnsEMBL/Utils/IO.pm
+++ b/modules/Bio/EnsEMBL/Utils/IO.pm
@@ -144,18 +144,18 @@ use Bio::EnsEMBL::Utils::Exception qw(throw);
 use Bio::EnsEMBL::Utils::Scalar qw(:assert);
 use IO::File;
 
-eval {
-  require IO::Compress::Bzip2;
-  require IO::Uncompress::Bunzip2;
-  $BZIP2_OK = 1;
-};
-
 eval {
   require IO::Compress::Gzip;
   require IO::Uncompress::Gunzip;
   $GZIP_OK = 1;
 };
 
+eval {
+  require IO::Compress::Bzip2;
+  require IO::Uncompress::Bunzip2;
+  $BZIP2_OK = 1;
+};
+
 eval {
   require IO::Compress::Zip;
   require IO::Uncompress::Unzip;
@@ -382,7 +382,7 @@ sub iterate_file {
 
 
 
-=head2 work_with_file()
+=head2 work_with_file
 
   Arg [1]     : string $file
   Arg [2]     : string; $mode 
@@ -415,7 +415,7 @@ sub work_with_file {
   return;
 }
 
-=head2 gz_work_with_file()
+=head2 gz_work_with_file
 
   Arg [1]     : string $file
   Arg [2]     : string; $mode 
@@ -464,6 +464,55 @@ sub gz_work_with_file {
   return;
 }
 
+=head2 bz_work_with_file
+
+  Arg [1]     : string $file
+  Arg [2]     : string; $mode 
+                Supports modes like C<r>, C<w>, C<\>> and C<\<>
+  Arg [3]     : CodeRef the callback which is given the open file handle as
+                its only argument
+  Arg [4]     : HashRef used to pass options into the IO 
+                compression/uncompression modules
+  Description : Performs the nitty gritty of checking if a file handle is open
+                and closing the resulting filehandle down.
+  Returntype  : None
+  Example     : bz_work_with_file('/tmp/out.txt.bz2', 'w', sub { 
+                  my ($fh) = @_; 
+                  print $fh 'hello'; 
+                  return;
+                });
+  Exceptions  : If we could not work with the file due to permissions
+  Status      : Stable
+
+=cut
+
+sub bz_work_with_file {
+  my ($file, $mode, $callback, $args) = @_;
+  throw "IO::Compress was not available"if ! $BZIP2_OK;
+  throw "We need a file name to open" if ! $file;
+  throw "We need a mode to open the requested file with" if ! $mode;
+  assert_ref($callback, 'CODE', 'callback');
+  $args ||= {};
+  
+  my $fh;
+  {
+    no warnings qw/once/;
+    if($mode =~ '>$' || $mode eq 'w') {
+      $args->{Append} = 1 if $mode =~ />>$/;
+      $fh = IO::Compress::Bzip2->new($file, %$args) or throw "Cannot open '$file' for writing: $IO::Compress::Gzip::Bzip2Error";
+    }
+    elsif($mode eq '<' || $mode eq 'r') {
+      $fh = IO::Uncompress::Bunzip2->new($file, %$args) or throw "Cannot open '$file' for writing: $IO::Uncompress::Gunzip::Bunzip2Error";
+    }
+    else {
+      throw "Could not decipher a mode from '$mode'";
+    }
+  };
+  $callback->($fh);
+  close($fh) or throw "Cannot close FH from ${file}: $!";
+  return;
+}
+
 =head2 filter_dir
 
   Arg [1]     : String; directory
-- 
GitLab