ディレクトリとファイルの操作

[14]ディレクトリとファイルの操作
1.ディレクトリとファイルの操作
Ruby にはDir、File、FileUtilsというディレクトリやファイルを操作する組み込みライブラリが用意されています。ここでは、その使い方を紹介します。なお、FileUtilsを利用する場合は、Ruby on Railsでは明示的なrequireは必要としませんが、Rubyではrequireが必要となります。

1-1.文字コード変換
Ruby on Railsと外部OSとのやり取りをする場合は、文字コードに注意しなければなりません。Ruby on Railsの世界ではUTF-8が使用されていますか゛、外部では異なるコード体系で動作していることが多くあります。そのため文字コード変換のライブラリが標準で用意されています。

(1) Kconv


require 'kconv'

filenames = Dir.glob('*') # 全てのファイル名をシフトJISコードで取得

filenames.each do |f|
p "****"
p f # ShiftJISのまま表示
p f.kconv(Kconv::UTF8, Kconv::SJIS) # ShiftJIS から UTF-8 に変換し表示
end

上記の例としてファイル名が”あいうえお.txt”であるとき
f => \202\240 \202\242 \202\244 \202\246 \202\250.txt
f.kconv => \343\201\202 \343\201\204 \343\201\206 \343\201\210 \343\201\212.txt
となります。

16進表現では
f => x82A0 x82A2 x82A4 x82A6 x82A8.txt
f.kconv => xE38182 xE38184 xE38186 xE38188 xE3818A.txt
です。

Kconvを利用するときは文字コードは次の定数で指定します。

定数文字コード
JISISO-2022-JP
EUCEUC-JP
SJISShift_JIS
BINARYバイナリ
ASCIIASCII
UTF8UTF-8
UTF16UTF-16

1-2.バックスラッシュ記法
プログラム内部では”あ い う え お”を”\202\240 \202\242 \202\244 \202\246 \202\250”のように文字そのものではなくコードで表現する場合があります。この表現方法の一つにバックスラッシュ記法があります。

バックスラッシュ記法意味
\tタブ(0x09)
\n改行(0x0a)
\rキャリッジリターン(0x0d)
\f改ページ(0x0c)
\bバックスペース (0x08)
\aベル (0x07)
\eエスケープ (0x1b)
\s空白 (0x20)
\nnn8 進数表記 (n は 0-7)
\xnn16 進数表記 (n は 0-9,a-f)
\cx\C-xコントロール文字 (x は ASCII 文字)
\M-xメタ x (c | 0x80)
\M-\C-xメタ コントロール x
\x文字 x そのもの

1-3.カレントディレクト
プログラムを起動したときカレントディレクトリは実行しているプロジェクトのディリクトリにあり、Ruby on RailsではRAILS_ROOTにパスが入っています。

1-4.プロジェクトの生成
(1) プロジェクトAppli022を生成する
(2) 日本語環境の設定
(3) データベースの作成

1-5.ディレクトリ操作のプログラム作成
(1) コントローラの生成
NetBeansで[生成..]を選択します。
    ジェネータ(G): controller
    名前(N): commands
    ビュー(V): index


実行結果
exists app/controllers/
exists app/helpers/
create app/views/commands
exists test/functional/
create test/unit/helpers/
create app/controllers/commands_controller.rb
create test/functional/commands_controller_test.rb
create app/helpers/commands_helper.rb
create test/unit/helpers/commands_helper_test.rb
create app/views/commands/index.html.erb

(2) コントローラの編集
Ajaxを利用し、ファイル操作の結果を同一画面に表示させながら進行するプログラムとしましょう。


/app/controllers/commands_controller.rb
class CommandsController < ApplicationController
def index
end

def operate_dir
filenames = Dir.glob('*') # 全てのファイル名を取得
@result="<br>" + File::expand_path('.') + ">dir <br>"
filenames.each do |f|
fn = f.kconv(Kconv::UTF8, Kconv::SJIS) # ShiftJIS から UTF-8 に変換し表示
@result = @result + fn + "<br>"
end
end

def operate_chdir
Dir::chdir(@strarray[1]) # カレントディレクトリの変更
@result="<br>" + File::expand_path('.') + ">chdir #{@strarray[1]} <br>"
end

def operate_mkdir
Dir::mkdir(@strarray[1]) unless File::exist?(@strarray[1]) # ディレクトリの作成
@result="<br>" + File::expand_path('.') + ">mkdir #{@strarray[1]} <br>"
end

def operate_rmdir
Dir::delete(@strarray[1]) # ディレクトリの削除(但し空であること)
@result="<br>" + File::expand_path('.') + ">rmdir #{@strarray[1]} <br>"
end

def operate_rename
FileUtils::mv(@strarray[1], @strarray[2]) # ファイル名やディレクトリ名の変更
@result="<br>" + File::expand_path('.') + ">rename #{@strarray[1]} #{@strarray[2]} <br>"
end

def operate
str=params[:commandarea][:commandline]
@strarray=str.split("\040", 3) # 最初の空白で文字列を分割し配列に格納
case @strarray[0]
def operate
when "dir"
operate_dir
when "chdir"
operate_chdir
when "mkdir"
operate_mkdir
when "rmdir"
operate_rmdir
when "rename"
operate_rename
else
@result="#{@strarray[0]} <br> command error <br>"
end
render :partial => "resultarea"
end

end

(3) レイアウトファイルの作成
Ajaxを利用するため、基本的なレイアウトファイルを作成します。


/app/views/layouts/commands.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Appli022: <%= controller.action_name %></title>
<%= javascript_include_tag :defaults %>
</head>
<body><%= yield %>

</body>
</html>

ここでRuby on Railsではjavascript_include_tag :defaultsと書いていますが、これは次のように展開されます。

<script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/javascripts/effects.js" type="text/javascript"><

/app/views/commands/index.html.erb
<h1>ディレクトリとファイルの操作</h1><% form_remote_tag :update => "resultarea",
:position => "top",
:url => {:action => "operate"} do -%>
Command: <%= text_field :commandarea, :commandline, :size => 80 %><% end -%>
<br/>

<div id="resultarea"></div>


/app/views/commands/_resultarea.html.erb

<%= "#{@result}" %>

1-6.動作確認
(1) 実装されたコマンドの種類

<
Command内容
dirカレントディレクトリ直下のディレクトリ名およびファイメ名の取得
chdirカレントディレクトリの変更
mkdirディレクトリの新規作成
rmdirデイレクトリの削除(但しディレクトリ直下は空であること)
renameディレクトリ名の変更

(2) 動作確認

1-7.ファイル操作のプログラム作成
(1) ディレクトリの操作プログラムの機能追加


/app/controllers/commands_controller.rb
class CommandsController < ApplicationController
def index
end

def operate_dir
filenames = Dir.glob('*') # 全てのファイル名を取得
@result="<br>" + File::expand_path('.') + ">dir <br>"
filenames.each do |f|
fn = f.kconv(Kconv::UTF8, Kconv::SJIS) # ShiftJIS から UTF-8 に変換し表示
@result = @result + fn + "<br>"
end
end

def operate_chdir
Dir::chdir(@strarray[1]) # カレントディレクトリの変更
@result="<br>" + File::expand_path('.') + ">chdir #{@strarray[1]} <br>"
end

def operate_mkdir
Dir::mkdir(@strarray[1]) unless File::exist?(@strarray[1]) # ディレクトリの作成
@result="<br>" + File::expand_path('.') + ">mkdir #{@strarray[1]} <br>"
end

def operate_rmdir
Dir::delete(@strarray[1]) # ディレクトリの削除(但し空であること)
@result="<br>" + File::expand_path('.') + ">rmdir #{@strarray[1]} <br>"
end

def operate_rename
FileUtils::mv(@strarray[1], @strarray[2]) # ファイル名やディレクトリ名の変更
@result="<br>" + File::expand_path('.') + ">rename #{@strarray[1]} #{@strarray[2]} <br>"
end

def operate_copy
FileUtils::cp(@strarray[1], @strarray[2]) # ファイルのコピー
@result="<br>" + File::expand_path('.') + ">copy #{@strarray[1]} #{@strarray[2]} <br>"
end

def operate_read
@result="<br>" + File::expand_path('.') + ">read #{@strarray[1]} <br>"
File::open(@strarray[1], "r") do |f| # ファイルの読み込み
while str=f.gets
@result += str + "<br>"
end
end
end

def operate_clearlog
@result="<br>" + File::expand_path('.') + ">clearlog <br>"
File::open(RAILS_ROOT + "/appli022_log.txt", "w+") do |f| # Logファイルの初期化
f.print "appli022_log.txt \n"
end
end

def operate_printlog
@result="<br>" + File::expand_path('.') + ">printlog <br>"
@result += "Begin VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV <br>"
File::open(RAILS_ROOT + "/appli022_log.txt", "r") do |f| # Logファイルの読み込み
while str=f.gets
@result += str + "<br>"
end
end
@result += "End VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV <br>"
end

def operate
str=params[:commandarea][:commandline]
@strarray=str.split("\040", 3) # 最初の空白で文字列を分割し配列に格納
case @strarray[0]
when "dir"
operate_dir
when "chdir"
operate_chdir
when "mkdir"
operate_mkdir
when "rmdir"
operate_rmdir
when "rename"
operate_rename
when "copy"
operate_copy
when "read"
operate_read
when "clearlog"
operate_clearlog
when "printlog"
operate_printlog
else
@result="#{@strarray[0]} <br> command error <br>"
end
File::open(RAILS_ROOT + "/appli022_log.txt", "a+") do |f| # Logファイルの追記型オープン
f.print @result, "\n"
end
render :partial => "resultarea"
end

end

1-8.動作確認
(1) 新たに実装されたコマンドの種類

Command内容
renameファイル名の変更
copyファイルのコピー

(ファイル名) → (ファイル名)

(ファイル名) → (フォルダ名)
readテキストファイルの読み込み
clearlogログファイルの初期化
printlogログのプリントアウト

(2) 動作確認



ProtoThickBox | index | OpenFlashChart