この記事で扱っていること
- ファイルを管理するプログラムを作る方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
LabVIEWのファイルIO関数は、何もファイルの読み書きだけにとどまりません。
ファイル操作として、特定のファイルを移動させたり、コピーしたり、削除することもできます。
そればかりでなく、ファイルやフォルダの作成、中身の確認、ファイルの情報を取得することもできます。
そのため、これらの関数を組み合わせて、ファイルを管理するプログラムを作成することができます。
機能追加はいくらでもできますが、自分の好みの機能を付けるにとどめたので、以下の役割を持たせるようにしました。
- 指定のフォルダの中身を表示させる
- 上の階層に移動、またはフォルダの中身に移動させる
- 任意のファイル、フォルダを作成、削除できる
- ファイルの基本情報(サイズや更新日時)を表示できる
- 指定のフォルダに指定のファイル、フォルダを移動したりコピーできる
これらの機能があれば一通りのファイル管理については問題ないかなと思います。
どんな結果になるか
プログラムのフロントパネルの例を示しています。

それぞれの機能ごとにボタンを押します。
- メインリスト更新ボタン:押すとファイルダイアログが表示され、フォルダを指定するとそのフォルダ内のファイルやフォルダをメインリストに表示する
- 上の階層へボタン:押すとメインリストとして現在指定しているフォルダの一つ上の階層へ移動
- 新規ファイルボタン:押すとメインリストで表示されているパスに新規のファイルを作成する
- 新規フォルダボタン:押すとメインリストで表示されているパスに新規のフォルダを作成する
- 削除ボタン:押すとメインリストで選択したファイルやフォルダを削除する
- 移動ボタン:押すとメインリストで選択したファイルやフォルダを移動/コピー先リストのパスに移動させる
- コピーボタン:押すとメインリストで選択したファイルやフォルダを移動/コピー先リストのパスにコピーする
- 移動/コピー先フォルダボタン:押すと移動/コピー先としたいフォルダを選択するダイアログが開く
- メインと同じにするボタン:押すと移動/コピー先リストがメインリストと同じパスになる
また、メインリストにファイルやフォルダが表示されるのですが、フォルダの場合ダブルクリックすることでその中身にアクセスできるようにしています。

ファイルやフォルダの削除を行おうとした場合、本当に削除してもいいかのメッセージを表示させます。フォルダの削除も行えるのですが、LabVIEWの削除の関数の仕様なのか、空のフォルダでないと削除できない(エラーが起こる)ため、それも警告を出すようにしています。

プログラムの構造
ベースはそれぞれの機能ごとにケースを設けた、ステートマシンで構成を行いました。ただしフロントパネルでのユーザー操作に応じて各ステートを移動させるので、より厳密にはイベント駆動型ステートマシンです。

それぞれのケースは以下のような実装としています。
まず一番最初に実行される初期化のステートです。以降で頻繁に使用されるファイル指定のパスの情報をまとめたクラスタを初期化しています。このステートの後にイベントを待つidleステートに移ります。

次にidleステートです。ここではイベントを待ちます。イベントに応じて次のステートが決まります。
各イベントによりステートが移った後、そのステートから再びこのidleステートに戻るため、その際にメインリストや移動/コピー先リストの状態を最新の情報にしておくために、このステートでフォルダをリスト関数を使用しています。配列連結追加を使用しているのは、ファイルとフォルダ、どちらもリストに表示させるためです。(プロパティノードは項目名プロパティを使用)

なお、各イベントケースの中身は以下のようです。

次のステートはメインリストおよび移動/コピー先リストで表示させるフォルダのパスを指定するmain_folder_selectおよびsub_folder_selectステートです。ファイルダイアログの関数を使用してフォルダのみを指定するようにしています。

次は、メインリストを上の階層に移るlevel_upステートです。やっていることは単純で、パスをストリップ関数で一つ上の階層にメインフォルダパスの情報を書き換えるだけです。同じく簡単な、移動/コピー先フォルダをメインリストのフォルダと同じにする、same_as_mainステートも示しています。

今度は、メインリストの項目がダブルクリックされたときに実行されるfolder_inステートです。こちらは、ダブルクリックされた項目がディレクトリ(フォルダ)であったときのみ、メインリストフォルダパスを変更するという作りにしています。

一方で、ダブルクリックではなく単にクリックされただけの場合にはfile_selectステートに移ります。クリックされた項目がショートカットなのか、ディレクトリなのかあるいはファイルなのかで、ファイル情報の文字列表示器に表示させる情報を変化させます。
ファイルだった場合には、ファイルのサイズと更新日の情報をファイル/ディレクトリ情報関数で取得しこれを文字列にフォーマット関数でフォーマットして表示させるようにしました。

次はファイルを作成するcreate_fileステートです。ここでは、ファイルを開く関数で新規のファイルを作るようにしているのですが、その際にファイル/フォルダ名制御器で指定したのと同じ名前のファイルが既にメインリストフォルダに存在している場合、ファイル名を変えるようにしています。
例えばファイル名としてtest.txtというものが既に存在し、同じパスにtest.txtを作成しようとするとtest_1.txtとなるようにしています。もしtest_1.txtという名前でかぶってしまった場合にはtest_2.txtと数値が自動的に変わるようにしました。

ファイル名を変える機能は上の図の中で使用しているサブviであるfile_name_optimizer.viで行っています。実際にはLabVIEWに既にある関数で「増分する接尾辞と一緒にファイルを作成」関数はあるのですが、この関数はファイル作成にしか使えず、後で出てくるフォルダ作成には使用できません。そのため、ファイルにもフォルダにも使用できるように自分で作ってみました。

名前はfile_name_optimizer.viとしていますが、フォルダにも対応しています。そのためブロックダイアグラムのケースが少しややこしいのですが、以下の作りとしました。

メインVIの方に戻ります。このサブVIは次の、フォルダを新規で作成するためのcreate_folderステートでも使用しています。

作成ときたら今度は削除のステート、deleteステートです。ここは慎重に、本当に削除してもいいかのプロンプトを出しています。また、LabVIEWの削除関数の仕様なのか、中身の入ったフォルダは削除することができない(エラーが出る)ので、エラーが出た場合にはダイアログとして「中身が空でないフォルダを削除することはできません」と表示させるようにしました。

あとはメインリストで選んだファイルやフォルダを移動/コピー先リストのフォルダに移動させるmoveステートと、コピーさせるcopyステートです。これらについても先ほど紹介したファイルやフォルダ名をかぶらせないようにするfile_name_optimizer.viを、ファイル拡張子を取得関数とともに使用しています。

移動させるのと同じような仕組みでコピーのステートも書けます。

あと残りはプログラムを終了させるcloseステートです。敢えて触れる必要もないと思いますが一応載せておきます。

このサンプルで実装したのは以上のステートです。
機能を考える
この記事のサンプルではかなりいろいろな機能を盛り込んだため、ステートの数も多くイベントの数も多くなってしまいました。
もちろん、自分の望みの機能を実装できるのがプログラム作りの醍醐味ですが、こんな機能必要ないというものはもちろん適宜抜くこともできます。ここら辺を簡単に追加、削除できるのがステートマシンの良さですね。
一方で、さらに機能を追加するのであれば、例えばフォルダをダブルクリックするとそのフォルダの中身を調べられたダブルクリックのイベントを使用して、ファイルをダブルクリックした場合にそのファイルの中身を表示させるような機能追加が考えられます。
この機能追加には呼び出したらフロントパネルを表示させるようなサブviを使用するのが便利だと思います。ただし、ファイルの中身によってはかなり読み取りに時間がかかるものもあるかもしれないため、読み込みの行数を制限するのが望ましいと思います。こちらについては以前挙げた記事が参考になると思います。
ただし読み込みに失敗してしまうようなテキストも考えられるため、そこは警告文を出すなり工夫をする必要があります。すべては工夫次第ですね。
ファイル管理をあえてLabVIEWで行う必要はないのかもしれませんが、自分の望みの機能を自由に構成できるというプログラムの醍醐味を味わえるようなサンプルとして参考になれば嬉しいです。
ここまで読んでいただきありがとうございました。
コメント