野狐消暇録

所感を記す

外部プログラムの呼び出しの話

Javaから外部プログラムを呼び出すための手順をまとめた記事をQiitaに書いて残す事にした。

qiita.com

この記事を書いたのには理由がある。

あるプログラムから、別の言語や環境のプログラムを呼び出すのは難しい事が多く、いつも苦労してきた。しかし、先日Javaから外部のプログラムを呼び出す処理を書いた所、思いの外容易に書く事ができた。そこで、この経験を纏めて書き残そうと思い、上述のQiitaの記事を書いたのである。

 

外部プログラムの呼び出しには、苦労した経験がある。

例えば、昔、Windowsのバッチファイルを使った事があった。

バッチファイルから別のバッチファイルを呼び出したのだが、ブロッキングしてくれず、平行して実行されてしまった。何かのコマンドだと、逐次実行されると聞いて試したのだが、なぜか駄目だったのだ。

他にも、外部プログラムの実行結果を呼び出し元で取得できなかったり、色々と難しい事が起こりがちである。

元々、ひとつのプログラムで実行したいと思っていて、呼び出し元の言語でうまくいかないから、外部プログラムを使う。そうすると、呼び出し元の言語内での単なるプロシジャ呼び出しで済んだ場合の簡便さが頭にあるから、余計大変な気がするのだと思う。

外部プログラムの呼び出しが面倒な理由をつらつら考えてみると、下記が挙げられるように思う。

  • 別のプロセスが起動され、プログラムが並列で実行されてしまう。

シングルスレッドで実行したい場合が多い。何もなければ、シングルスレッドで書きたい。しかし、外部のプログラムを呼び出すと、そこで新しいプロセスが開始されるので、意識して同期を取る必要が出てくる。先に挙げたバッチファイルが並列して実行されてしまったというのは、ここの絡みである。

  • エラー処理が難しい。

外部プログラムの実行結果が容易に分からない。

外部プログラムの終了コードを取れる場合があるが、それ以上の内容となると、外部プログラムが出力する標準出力や標準エラー出力をどこかのファイルに書き出し、そのファイルを読み込むとか、何か方法を考えねばならない。

 

そんな訳で、色々面倒だった記憶があり、自分はつい最近まで、外部プログラムの呼び出しをあまりしたくないと思っていた。しかし、この間、Javaコードで圧縮ファイルの解凍処理を書いたらうまくいかず、止むを得ずJavaから圧縮解凍ソフト「7-zip」を呼び出した所、案外その処理がスムーズにいったので、感動したのである。

Qiitaに記事を書いていて思ったのは、外部プログラムの標準出力、標準エラー出力の出力先をリダイレクトするAPIがあり、ProcessBuilderクラスのredirectOutputメソッド辺りがそうなのだが、これがJava1.7で追加との事で、有難く思った。Javaの標準ライブラリのサポートが、外部プロセスの呼び出しに関して厚くなってきているとしたら、とても嬉しい事である。

  • まとめ

外部プログラムの呼び出しの難しさというのは、結局は平行処理の難しさなのではないか。

異なるプロセス間で適切に連携を取る事の難しさが、外部プログラムの呼び出しにはあると思う。

『Effective Java』がめっちゃ勉強になる。

 

  • 概要

『Effective Java』を久しぶりに開いてみたら、心に響いた。

  • 詳細

『Effective Java』を購入したのは、何年も前の事で、その時の事はもう覚えていない。確か評判がいいと聞き、試しに買ってみたのだと思う。しかし、内容をあまり覚えていないから、おそらく難し過ぎて、そのまま読まなかったのだろう。

久方ぶりに開いた『Effective Java』は、Javaを2年位書きまくった僕の脳天に痛棒を食らわした。

「君、この位は分かっていたまえ。Javaは手続き型じゃないんだから」

『Effective Java』は、ちょっと上から目線でそう言った。

「この前君が書いていたコードだが、最初はHashMapで実装した。その理由は確か、KeyとValueを辞書のように使えれば良く、特に順序を考慮する必要はないから、だったね。だから君は、TreeMapを使わなかった。しかし、途中で、事情が変わり、Keyの昇順に並び替える必要が生じた。その時君はどうした? 一度全ての値をHashMapから取得し、ArrayListに格納した。そして、そのリストを並び替えた。つまり、TreeMapを使わなかった。なぜならもしその時からTreeMapに書き換えるとなると、修正箇所が多く、コードを書き変えるのが面倒だったからだ。しかしだ、それはなんでだと思う。修正箇所が多かったのは、止むを得ない事情でも何でもない。君の書き方が悪いからだ。君はHashMapを生成した後、そのインスタンスをHashMap型の変数に格納していた。しかし、Javaにはインターフェースという機能がある。Mapインターフェースにインスタンスを格納しておけば、インスタンスを生成する箇所で、生成するインスタンスのクラスをHashMapからTreeMapに修正するだけで良かった筈だ。そうすれば、Mapから取得したコレクションは、TreeMapクラスの力により、順序が保証されたのである。分かるか? 君が愚かだからだ。結論はそういう事だ」

 「Enumの書き方もそうだ。なぜそうやすやすとEnumでswitchしてしまうんだ。Enumにはもっと効果的な使い方がいくらでもある。switch文で分岐させる代わりに、Enum型の内部で抽象メソッドを宣言し、列挙定数ごとに抽象メソッドを実装したっていい。そうすれば、列挙定数を追加した時に、switch文にひとつ列挙定数を追加し忘れる事もない。またswitch文の最後に、定型的なエラーをスローする処理も書かないで済む」

「他にも言いたい事は山ほどあるが、今日はこの辺にしておこう。あまり一度に話しても混乱するだろうから」

JavaFXを使ってみたのだった。

会社で、技術勉強会を催す事になった。何と責任者は僕である。
...
やりましょう。

最初、AOJとか、そういうプログラミング・コンテストを通した勉強をイメージしていたのだが、参加者の提案で、月ごとの持ち回りの、発表形式になった。1月に一度、誰かが勉強した事をみんなの前で発表する。
僕は技術関連の発表をした経験がなく、どういう事をすればいいのか、はっきりとしたイメージはなかったが、ともかく勉強会を始める事が先決だと思った。最初の発表者は自分にした。また、発表時期は月末にした。そうすると、発表まで、時間がない。2週間ちょっとしかない。
考えた末、JavaFXをやってみる事にした。

JavaFX テクノロジーの概要

Oracleの技術である。ここで出てくるJavaはそう、あのプログラミング言語Java」である。JavaFXとは、一言で言うと、Javaで作るUIである。
まずは下記のサイトで勉強だ。

初心者のためのJavaFXプログラミング入門

チュートリアルって感じのサイトである。JavaFXはSwingに変わって新しく登場した、JavaのUI作成技術なのだ。
このサイトで学んでて感心したのが、JavaFXXMLでUIを作るという事。そういう点では、Androidに近いのかしら。でも、Androidで使っているJavaは公式じゃない?んだってね。GoogleOracleが争っているってどこかで読んだよ。このXMLはFXMLと名付けられていて、名前の由来はJava"FX"と"XML"を掛けているんだと思うな。

ここでちょっとFXMLの例を挙げたいのだが、会社の勉強会向けに作った物をここで挙げていいのか、分からないので止めよう。

あと、JavaFX向けのCSSというのもある。これはWebサイトを書くときにHTMLと一緒に使うあのCSSとはやや違うらしいのだが、目的は一緒だ。

これも例を挙げたいんだけど、会社向けのやつだから止そう。というか、上記に挙げたチュートリアルサイトに全部載っているから、そっちでいいよ。

なんか情報量ゼロになってきた。これだけ書いたのに、情報量ゼロ。なるほど、これがゴミブログだな!

あとですね、FXML内で、スクリプト言語が使えるのだよ。JavaScriptClojureやGroovyとか。使えるはずだよ、エラーになっちゃって自分は使えなかったけど。

なぜコンパイルエラーごときで諦めたかと言えば、あまり僕の作ったサンプルで、スクリプト言語を使う必然性がなかったからなんだよ。

だって、Javaで書けるんだよ。JavaFXは入力ボックスとか、プルダウンメニュー、ラジオボタン、日付選択用のピッカー、ボタンなど、色々なコントロールを配置できる。それを押したり、選んだりしたとき、ちゃんとそのアクションをJavaで受けて、イベント駆動できるのだ。とすると、ちょっとスクリプトの使いどころが分からなかった。スタンドアローンでアプリを書いて、そのUIをJavaFXで作ったとしたら、要らないと思う。多分、リッチクライアントという事なので、別の使い方があるのではないかと思っている。Webサイトで、このXML+CSS+軽量言語を閲覧できるようになる? ちょっと分かってない。Adobe Flashみたいな使い方ができるそうなんだけど。

僕がJavaFXを使ってみて思ったのは、企業で自社向けツールを書いた時、開発した本人以外の人が実行する時に使うUIをJavaFXで書くのが良いのではないかという事。Javaツールを作ったら、UIもJavaで作れると一貫して開発できていい。ちょっとしたUIなら、まず問題ないだけのコントロールやCSS機能が入っていそうだ。

そういう点で、MicrosoftVisual Studioで作るフォームアプリケーションのフォーム部分みたいなのが、Javaでもできる、という事なんじゃないかね?

あと、書き忘れていたが、JavaFX Scene Builderという、GUIベースでFXMLが記述できるツールOracleが配布している。

JavaFX Scene Builder Information

上記サイトのサブタイトルに「A Visual Layout Tool for JavaFX Applications」とあるが、まさにその通りだ。以下の画像は起動した所。

f:id:nogitsune413:20150505035523j:plain

こんな技術があるんだな。Javaの世界は広い。

 

会社で作ったJavaツール

  • 発端

スクリプトを書いてくれ」

最初はそう言われたのだった。

しかし、話を聞くうちに分かってきた。

これはスクリプトでは済まない。

そこで、使用する言語をPowerShellから急遽Javaに変更した。近頃、Javaで書くシステムはWebシステムが多かったが、仕事でコンソールプログラムを書く事になった。

  • ライブラリ

HTMLをパースする。XMLをパースする。パースというのは解析という事で、プログラムがHTMLを解釈してデータを取得するのである。XMLも同じである。

これはJavaの標準機能ではできない。ライブラリを使う事になった。

[Jsoup]

jsoup.org

これでHTMLをパースした。出力も出来る。お世話様だ。

[dom4j]

sourceforge.net

これはね、最初はJava標準のXMLパーサでいけると思ってたんだ。ところがどっこい、読み取りはまぁいいんだけど、書き込みができない。

全然できない訳じゃないんだけど、ちょっと難しそうだったんだ。

因みに標準は、javax.xml.parsersというのらしいんだけど、うまく使えなかった。時間がかかりそうだったので、ネットで評判の良さそうなdom4jにした。

[jaxen]

http://jaxen.codehaus.org/

これはdom4jに必要なライブラリだったんだけど、XPathというものを使えるようにするライブラリだ。このXPathというのが、今回自分には大きな発見だったんだな。

詳しくはググって欲しいんだけど、以下のMicrosoftのページが分かりやすいな。

XPath の例

要は、SQLのように、XMLから指定した集合を抽出できる言語が、XPathだ。これは誰かが勝手に考えたという訳ではなくて、 標準化団体W3Cで開発されたという事で、それなりに権威があるというか、公式な感じの言語だと思う。

これがまぁ面白いね。

先のMicrosoftのサイトにある例で、

x[1]/y[2] → 最初の <x> の 2 番目の子要素 <y>

とある。SQLっぽいと言いつつ、順序も扱える所、なかなか。

  • plist

iOS系の開発をする人は知っていると思うんだけど、plistというのは、XML形式のファイルで、iOSで使っている設定ファイルだ。これを今回生成する事になった。

iOSで使うファイルをWindows上で動くJavaで生成する。

俺は何をやっているんだ。plistを生成しているんだ。

そんな事を開発中に考えてしまったよ。

  • 環境

個人的というか、要件は「ちゃんと出力しろよ」というだけだから、使うツールや環境に殆ど制約のない開発だった。それでJava8を使ったんだけど、使い慣れていないものだから、あまり新機能、ラムダ式とか使えなくて、残念だった。でも、Java7から入った、ファイル操作系のクラス、「Files」「Paths」なんかはガンガン使わせてもらった。初めてtry resourcesも使って便利だったよ。やっぱりバージョンアップは大事だな。自慢にならないけど、ついこの間まで、Java1.4だったんだ。Java6に上がって嬉しかったんだけど、もう8の時代だ。ようやく時代に俺が追い付いたって感じかな。

 

--  追記  2015/04/19  --

このツールに機能を追加する事になった。

具体的には、Androidで使うpreferences.iniファイルを生成する。

このpreferences.iniというのは、設定ファイルだ。key=valueという形式で値が書いてある、簡易なデータベースといった所。テキストで扱える。

ええと、こいつを読み込んで編集するのか。どうしようかな。ライブラリ、だな。これは確か標準ライブラリにクラスがあったな。あったあった、これだ。Propertiesクラス。

。。。ちょっと違うな。

セクションが扱えないのではないか?

セクションというのは「[」と「]」で囲んだセクション名を見出しのように置くと、設定項目の組を作れるというものである。例えば、以下である。

ーーーーーーーーーーーーーーーーーーーーーーーーーーー

[Animal]

fox=3

rabbit=1

cat=7

[bird]

pigeon=2

peacock=3

ーーーーーーーーーーーーーーーーーーーーーーーーーーー

preferences.iniではセクションを使っているから、セクションが扱えないと駄目だ。

また外部ライブラリかよ。別にいいけど。

ini4j.sourceforge.net

標準ライブラリのPropertiesクラスを諦めて、これを使いました。ini4j。ちっちゃいライブラリで可愛い。

それで、まぁつまらないこだわりなのですが、INIファイルを生成した時、自分の意図した通りの順番で上からセクションを並べたい。Androidのpreferences.iniは手で編集する事も充分あり得るから、綺麗に出力したいのです。しかし、このライブラリはMapというデータ構造で、INIファイルを読み込むのですな。Mapというのは、KeyとValueを紐付けて一組とし、これをたくさん保持するのですが、基本的に順序性はないのですよ。Javaの場合、TreeMapというクラスがあって、これなら、順序も扱えるのですがね。まぁそれで無駄に悩みました。

...

そうだ、一から値を格納していけば、きっと格納した順序で出力されるに違いない。設定ファイルからini4jに読み込んだ状態で編集して、そのまま書き出そうとするのではなく、一旦値を全部ini4jからアプリに取り出して編集し、ゼロクリアした状態のini4jに編集後の値を入れ、書き出してみよう。

そうやって書いちゃいました。

今は動いています。今後は知りませぬ。いざとなれば、ライブラリを使わずにアプリで書き出すしかないが、今の所うまく動いているので、そのままである。

女性とご縁がない。

どうも結婚できそうにないので、困った。

しかし、今日思ったのは、こういう事だ。

人を愛するという事を、もっと広く考えたい。

例えば、この間、人口問題を調べたら、途上国で人口が増えているという。女性一人当たり、平均で5人子供をもうけるとその記事にあって、すごいな、日本と偉く違うなと思った。しかし、そういう国では、貧困により、子供が働かざるをえない状況があるという。もちろん、働くことはいけないことではない。しかし、家の手伝いとかそういう事ではなくて、子供がこき使われるという事は、また別の話だ。ちょうど日本に技能研修生で来た人がこき使われているのに近いだろうと思う。

それで、気の毒に思った。そこで考えたのだが、そもそも、自分が結婚するのは、自分の幸せのためにそれでいいと思う。しかし、子供という事を考えると、自分の年齢だと、おそらく子供はできないだろう。しかし、それは残念ではあるだろうが、今、現に生まれていない子供の事は、まぁある意味で、どうでも良いとも考えられると思う。それは、今もうこの世に生を受けていて、困っている子供の事を考えると、そう思うのである。

それで、これは自分にもしお金に多少余裕があるなら、少し、信頼できる団体を通じて、寄付を行うという事も有りかなと思う。

つまり、現に生きていて、困っている子供に対して、できる事をするというのも、愛情の表現かもしれないなと思ったのである。

人は愛されたいとも考えるのであるが、愛したいという事も、同時にあると思う。それは決して傲慢ではない。人を愛するというと、そこに上下の関係を見て、愛する方が愛される方を見下しているかのように考える人もいるかもしれないが、僕はそう考えないのである。

例えば、医者というのは、患者の病を治している。これは普通に言われる愛情とは違うが、人を救っているという点で、愛情の表現として考える事ができるのではないかと思う。この時、医者は地位が多少高く見られることもあるが、基本的には、上下の関係というのは、ないのではないかと思う。患者の方が、医者よりも格下であるとは思えないし、みんなそんな風には思わない。

だから、愛情という事に、上下の関係を見ずに、相互に愛情を持つという事があり得ると思う。

自分は愛情の表現という事を、単に家庭というひとつの形に限定するのではなく、広い可能性として考えて、自分なりに道を見い出したいと思っている。

それが今日考えた事である。

PowerShell 便利。

WindowsOSに標準装備されているスクリプトといえば、VBScriptだった。あとは、コマンドを並べる事しかできないcmd.exe。それがどうよ! PowerShell !!! ついに来ました、便利スクリプト。何しろ、Microsoftはこの言語をこれから押していくそうです。どう押すか? このシェルを基本にして、上にGUIをかぶせるとか。関係者じゃないので、あまり断言できませんが、もしそうだとすると、GUIでできることは全てPowerShellでできる事になる。

ありがとう、PowerShell。君と共に歩もう。

 

PowerShellのどこが良いか?

・パイプをオブジェクトが流れる。

オブジェクトが「|」の次に書かれた関数に渡される。だから、パイプ「|」という書き方ができるだけで、要するに引数みたいなものなのではと思います。記法の一種なのかな。Linuxとかに付いているShellScriptだと、パイプをテキストが流れたと思うんですよ。その方が便利な場合も、あるかもしれません。でも、僕はあまりテキストをプログラム内部で扱いたくないのです。全て、型安全の中で、コーディングしたいと願っている。テキストをParseするのは、ファイル読み込みの時だけでいいじゃないか、という。だから、嬉しかった訳。普通のプログラミング言語じゃん。いいじゃん。

・開発環境「ISE」が付いている。

すっかりJavaの開発者になってしまい、Eclipseでコーディングするのが日常になりました。そうすると、テキストだけでプログラミング、やりたくないですよね。本当に些細なエラーまで自分で見つけなきゃいけない。漸く開発環境がWindowsスクリプト書くにも付属するようになった。嬉しい。ああ、嬉しい。ほら、VBScriptは、テキストに書いていたから。Windows Batch fileも、テキストだった。

 ・ISEのコードハイライトが綺麗

コードのハイライト、というか文字色の色分けなんですが、色合いが渋好み。なんていうか、「あ、綺麗」みたいな感じで、嬉しい。

 

◆ 最新のPowerShell

喜んでコーディングしていた訳ですが、「そうだ、圧縮しよう」という訳で、圧縮したいと思った。でも、圧縮するコマンド?が付いているPowerShellって、v5?とか、結構後ろのバージョンなんですよね。

僕のWindows7に入っているPowerShellのバージョンはv2でした。

そっかーというところ。

ま、鋭意進化中という事で、この事自体は前向きに捉えたい。

拡張を入れれば、現バージョンでも圧縮処理できそうなんですが、特に強い要件ではなく「できれば」位だったので、無視無視!

圧縮しないで、backup!!!

という事にしました。

問題になったら、対処しようかな。。。

 

◆ まとめ

前々からPowerShellいいなとは思っていたんですが、商用で使われているWindows Serverのバージョンがちょっと古かったり、作業用PCに標準装備されていなかったりで、ちょっと使い辛かった。しかし、いつの間にか時は経った。知らないうちにPowerShell自体のバージョンもそれなりに上がった。Micriosoft製品はPowerShellをサポートするものが多くなった。古いの以外はみんなサポートしていそうだ。

いいスクリプト言語Microsoft製品で使えるようになってほっとしている。

この位書きやすくなきゃね!!!