【Ruby入門】zipファイルの圧縮・解凍・パスワードの指定

こんにちは!システムエンジニアのオオイシです。

Rubyでzipファイルの圧縮や解凍方法を知っていますか?

rubyzipというライブラリを使えばRubyでzipファイルの作成や解凍が可能です。

この記事では、

  • rubyzipをインストール
  • ファイルをzip圧縮する
  • zipファイルを解凍する
  • パスワード付きzipファイルの作成する
  • パスワード付きzipファイルの解凍する

といった基本的な内容から、

  • ディレクトリを圧縮する
  • 解凍せずにzipファイルを読み取る
  • Rubyの文字列からzipファイルを作成する

などの応用的な使い方に関しても解説していきます!

今回はこれらの方法を覚えるために、Rubyでzipファイルを扱うためのさまざまな使い方をわかりやすく解説します!

目次

rubyzipの使い方

rubyzipをインストールする

Rubyでzipファイルへの圧縮や解凍をするにはいくつかの手段がありますが、「rubyzip」というライブラリを使う方法が一般的なので、この方法について解説します。

まずはじめにrubyzipのgemをインストールしましょう。

gem install rubyzip

実行結果:

Fetching: rubyzip-1.2.1.gem (100%)
Successfully installed rubyzip-1.2.1
Parsing documentation for rubyzip-1.2.1
Installing ri documentation for rubyzip-1.2.1
Done installing documentation for rubyzip after 0 seconds
1 gem installed

gemとは、Rubyのパッケージ管理システムです。

gemを知らない場合は、こちらで詳しく説明していますので参考にしてください。

では、次の項でさっそくzipファイルを扱ってみましょう!

ファイルをzip圧縮する

rubyzipには、zipファイルに圧縮するために使用する「Zip::OutputStream」クラスがあります。

「Zip::OutputStream」クラスの使い方のイメージは、zipファイルへ小川(Stream)が流れるように書き込みを行います。

ここでは、基本的な使い方を知っていただくために、1つのファイルをzip圧縮する方法をサンプルコードを交えて解説します。

サンプルプログラムで使うファイル構造は次のとおりです。

.
├── compress.rb
├── input
│     └── file_name.txt
└── zip_file.zip
  └── output
       └── file_name.txt

たくさんのファイルがありますが、丁寧に説明するのでご安心ください!

それぞれファイルの役割は次のようになります。

ファイル名説明
compress.rbzipファイルを作成するサンプルプログラム
input/file_name.txt圧縮元のテキストファイル
zip_file.zipプログラム実行後に作成されるzipファイル
output/file_name.txtzip_file.zipの中に圧縮されたファイル

まずは、プログラムを実行する前準備として、圧縮元のテキストファイル(input/file_name.txt)を作成してください。

テキストファイルの内容は任意ですが、今回は次のようにしました。

1行目
2行目

それでは、”input/file_name.txt”の1つのファイルを”zip_file.zip”ファイルへ圧縮するサンプルプログラムを確認してみましょう。

require 'zip'

file_name = "file_name.txt"
zip_file_name = "zip_file.zip"

# 作成するzipファイルのパスを引数に指定
Zip::OutputStream.open(zip_file_name) do |out| 

  # zipファイル内に書き込むファイルのパスを指定
  out.put_next_entry("output/" + file_name) 

  # zipファイルへ文字列を書き込む
  buffer = File.read("input/"  + file_name)
  out.write(buffer)
end

実行してみましょう。

ruby compress.rb

実行した結果、”zip_file.zip“が作成されます。

このサンプルプログラムでは、

  • out.put_next_entry(zipへ書き込むファイルのパス)
  • out.write(zipへ書き込む内容)

で、2つのメソッドを使ってzipファイルへ書き込みができる点について解説しました。

「Zip::OutputStream」クラスのメソッドは次のようなものがあります。

メソッド名用途・目的
open圧縮するzipファイルのパスを引数に指定。
ブロックには「Zip::OutputStream」のインスタンス変数が渡る
put_next_entryzipファイルに登録するファイルパスを引数に指定
writeput_next_entryに指定したファイルパスに書き出す文字列を引数に指定

以降の説明は、この解説の応用になるので簡単にわかっていただけると思います!

また、サンプルプログラムの中で登場したFileクラスについては、こちらで詳しく説明していますのでぜひ参考にしてください。

zipファイルを解凍する

rubyzipでは、zipファイルを解凍するために「Zip::InputStream」クラスを使います。

「Zip::InputStream」クラスの使い方のイメージは、小川(Stream)が流れるようにzipファイルを読み込みます。

それでは、前項のプログラムで作成した”zip_file.zip”ファイルを解凍するサンプルプログラムについて解説していきます。

今回のファイル構造は次のようにしました。

.
├── uncompress.rb
└── zip_file.zip
  └── output
         └── file_name.txt

それぞれファイルの役割は次のようになります。

ファイル名説明
uncompress.rbzip_file.zipを解凍するサンプルプログラム
zip_file.zip前項のサンプルプログラムで作成したzipファイル
output/file_name.txtzip_file.zipの中のテキストファイル

それでは、サンプルプログラムを確認してみましょう。

require 'zip'

zip_file_name = "zip_file.zip"

# 解凍するzipファイルのパスを引数に指定
Zip::InputStream.open(zip_file_name) do |input|

  # 次に取得できるzip内のファイル情報を取得
  entry = input.get_next_entry

  # 解凍するディレクトリを作成する
  Dir.mkdir(File.dirname(entry.name))
  
  # entry.nameでzipファイルのパスを取得
  file_name = entry.name

  # zip内ファイルの内容を読み込み
  buffer = input.read

  # ファイルに書き出し
  File.write(file_name, buffer)
end

実行してみましょう。

ruby uncompress.rb

実行した結果、”1行目<改行>2行目“という内容テキストファイルが”output/file_name.txt”に作成されました。

このサンプルプログラムでは、

  • input.get_next_entry → zip内で取得可能なファイルの情報を取得
  • input.read → ファイルの読み出し

の2つのメソッドを使ってzipファイルを解凍できることを解説しました。

「Zip::InputStream」クラスの代表的なメソッドは次のとおりです。

メソッド名用途・目的
open解凍するzipファイルのパスを第1引数に指定
get_next_entryzipファイル内のファイル情報を返す
readzipファイル内のデータを読み取り返す

また、サンプルプログラムの中で登場したDirクラスについては、こちらで詳しく説明していますので、ぜひ参考にしてください。

パスワード付きzipファイルを取り扱うには

パスワード付きzipファイルの作成

rubyzipではパスワード付きのzipファイルを作成することができます。

セキュリティー上の理由からzipファイルにパスワードを付与することは、いまや常識となっているので、ここで覚えておくと何かと役に立ちます!

そんなパスワードつきのzipファイルの作成も、これまでの解説の応用なので作成はとってもカンタンです!

require 'zip'

file_name = "file_name.txt"
zip_file_name = "password_zip_file.zip"

# zipパスワードを作成
password = Zip::TraditionalEncrypter.new('password')

# 第2引数にパスワードを指定
Zip::OutputStream.open(zip_file_name, password) do |out|
  out.put_next_entry("output/" + file_name)

  out.print("1行目\n")
  out.print("2行目\n")
end

このプログラムを実行した結果、パスワード付きの”password_zip_file.zip“ファイルが作成されます。

次は、Rubyプログラムでパスワードつきのzipファイルを解凍する解説をします。

パスワード付きzipファイルの解凍

rubyzipではパスワード付きのzipファイルを解凍することができます。

前項で作成した、パスワード付きzipファイルの”password_zip_file.zip”を解凍するサンプルプログラムを確認してみましょう。

require 'zip'

zip_file_name = "password_zip_file.zip"

# zipパスワードを作成
password = Zip::TraditionalDecrypter.new('password')

# 第3引数にパスワードを指定、第2引数は0固定
Zip::InputStream.open(zip_file_name, 0, password) do |input|
  entry = input.get_next_entry

  Dir.mkdir(File.dirname(entry.name))
  File.write(entry.name, input.read)
end

実行した結果、パスワード付きzipが解凍されて”output/file_name.txt”にファイルが出来上がります。

このように「Zip::InputStream.open」メソッドの第3引数にパスワードを指定するだけで、パスワード付きzipファイルを、カンタンに解凍するできることが理解いただけたと思います!

また、サンプルプログラム中のDir.mkdirメソッドについてはこちらで詳しく説明していますので、ぜひ参考にしてください。

ディレクトリを圧縮する

ディレクトリ内の全てのファイルを含んだzipファイルを作成する方法を確認してみましょう。

今までの解説で登場した「Zip::OutputStream」クラスを使った応用ですので、新しいことを覚えずに実現できます。

このサンプルプログラムでは”input_dir”フォルダ内の全てのファイルを”input_dir.zip”ファイルへ圧縮する例です。

プログラムを実行する前には”input_dir”フォルダへ圧縮したい任意のファイルをコピーするなどして準備しておいてください。

require 'zip'

zip_file_name = "input_dir.zip"

#input_dirフォルダ内のファイル名を配列に登録
entries = Dir.glob("input_dir/*")

Zip::OutputStream.open(zip_file_name) do |out|
# input_dirフォルダ内のファイル名のループ
 entries.each do |entry|
 # ファイルパスのうち、ファイル名のみを取得する
 file_name = File.basename(entry)
 # zip内にファイル名と内容を登録
 out.put_next_entry("output_dir/" + file_name)
 out.write( File.read(entry) )
 end
end

実行した結果、”input_dir.zip“が作成されるので、ソフトで解凍してファイルの内容を確認してみてください。

解凍せずにzipファイルを読み取る方法

rubyzipでは、zipファイルを解凍せずにzip内のファイルを読み込むことが可能です。

zip内のテキストファイルを読み取るには、1行ごとに文字列を取得するために使用するeach_lineメソッドを使うと便利です。

前章のサンプルで作成した”zip_file.zip“内のテキストファイルを読み取るサンプルプログラムを確認してみましょう。

require 'zip'

zip_file_name = "zip_file.zip"

# 読み取るzipファイルのパスを引数に指定
Zip::InputStream.open(zip_file_name) do |input|

  # zip内のファイル情報を取得
  entry = input.get_next_entry

  puts "zip内のファイルパス: #{entry.name}"

  # zip内のファイルを改行コード毎にループ
  input.each_line do |line|
    puts line
  end
end

実行結果:

zip内のファイルパス: output/file_name.txt
1行目
2行目

このように、”zip_file.zip“ファイル内の”output/file_name.txt”の内容を読み取って、putsメソッドで出力することができました。

each_lineメソッドを使うと、zip内のテキストファイルを改行毎に処理できることがわかっていただけたと思います!

each_lineメソッド以外にも、Rubyプログラムで使える次のような便利なメソッドがあるので、ぜひ使ってみてください!

メソッド名用途・目的
each_lineファイル内の文字列を行毎に読み取り、ブロックの変数に渡す
readlinesファイル内の文字列を行毎に読み取り、配列で返す
read画像や文字列などのバイナリデータを読み取る

文字列からzipファイルを作成する

rubyzipではRubyプログラムからzipファイルへ直接書き込むことができます。

今まで解説したサンプルプログラムの応用なのでカンタンに実現することできます。

zipファイルに2つのテキストファイルを作成し、文字列を書き込むサンプルプログラムを確認してみましょう。

require 'zip'

file_name1 = "file_name1.txt"
file_name2 = "file_name2.txt"
zip_file_name = "zip_file.zip"
 
Zip::OutputStream.open(zip_file_name) do |out|
  # zip_file.zip内の output/file_name1.txt へ書き込み
  out.put_next_entry("output/" + file_name1)
  out.print("#{file_name1} 1行目\n")
  out.print("#{file_name1} 2行目\n")

  # zip_file.zip内の output/file_name2.txt へ書き込み
  out.put_next_entry("output/" + file_name2)
  out.print("#{file_name2} 1行目\n")
  out.print("#{file_name2} 2行目\n")
end

実行した結果、”zip_file.zip“ファイルが作成できるので、ソフトで解凍すると、次のようなファイルが作成されています。

output/file_name1.txt:

file_name1.txt 1行目
file_name1.txt 2行目

output/file_name2.txt:

file_name2.txt 1行目
file_name2.txt 2行目

このように、Rubyプログラム内からzipファイルを作成できることができました。

その他にもzip内のファイルへ書き出すために、次のような便利なメソッドがあります。

メソッド名説明
print引数に指定した文字列または配列をzip内のファイルに出力
putsprintメソッドと同様。違いは改行コードを行末に自動挿入
printf第1引数に指定した書式で、2引数の文字列をzip内のファイルに出力
putc引数に指定した1文字または1桁の整数をzip内のファイルに出力
write引数に指定した文字列や画像などのバイナリデータをzip内のファイルに出力

また、printfメソッドの書式についてはこちらで詳しく説明していますので、ぜひ参考にしてください。

まとめ

いかかでしたか?

今回はrubyzipを使ったzipファイルへの圧縮や解凍方法の使い方について説明しました。

rubyzipを使うとパスワード付きのzipファイルの作成や解凍を処理することが可能です。

rubyzipを使うとプログラム内からzipファイルの読み取りや書き込みしたい場合に大変便利になので、ぜひ活用してください。

そして、rubyzipの使い方を忘れてしまったらこの記事を確認してくださいね!

この記事を書いた人

システムエンジニア歴15年のオオイシです!好物は Java と Ruby。プログラミング、システムアーキテクトからマネジメントに到るまでなんでも食べます。
システム開発の相談やお困りごとがあればお気軽に
makoto.oishi.0705@gmail.com まで連絡頂けると幸いです

目次