読者です 読者をやめる 読者になる 読者になる

ハイパーニートプログラマーへの道

頑張ったり頑張らなかったり

【Windows】 SublimeText2でJavaをコンパイル&実行させる

今受講しているJavaの講座で「Sublime Text2使ってるんなら入れようぜ! しかもその上でJavaコンパイル&実行できるようにしよう!」ということになり「は、はい(震え声(しかもWindowsか・・・))」と丸1時間ほど先生とあーでもないこーでもないと試みたわけですが・・・

家に帰ってから地獄を見ることになるとはつゆ知らず・・・

http://programming-10000.hatenadiary.jp/entry/20130415/1366050305

↑ここを参考に
Sublime TextのPreferences > Browse Packages > Java > JavaC.sublime-buildを開いて

{
 "cmd": ["javac", "$file_name","&&","java", "$file_base_name"],
 "file_regex": "^(...*?):([0-9]*):?([0-9]*)",
 "path": "C:\\Program Files\\Java\\jdk1.7.0_04\\bin\\",
 "selector": "source.java",
 "shell": true
}

パスは\\で区切る。
Tools > Build System > JavaC.を選択。
javaのファイルをtools > buildかあるいはCtrl+bでビルドが実行。
その時に

[Decode error - output not utf-8]

というエラーが出た場合は、以下のようにする。

{
 "cmd": ["javac", "$file_name","&&","java", "$file_base_name"],
 "file_regex": "^(...*?):([0-9]*):?([0-9]*)",
 "path": "C:\\Program Files\\Java\\jdk1.7.0_04\\bin\\",
 "selector": "source.java",
 "shell": true,
 "encoding": "cp932"
}

ほぼこのまんまでやればよい。後にバッチファイル当てたので、ちょっと書き換えることになりますが。

で、上記記事では

カレントディレクトリにクラスパスが通っていなかったからメインクラスを見つけることができなかったのだ。

ということでバッチファイルを書いたそうです。自分の場合はそうだったかどうか覚えていないのであれですが、書いてみます。

・runJava.bat

@ECHO OFF
cd %~dp1
ECHO Compiling %~nx1.......
IF EXIST %~n1.class (
DEL %~n1.class
)
javac %~nx1
IF EXIST %~n1.class (
ECHO -----------OUTPUT-----------
java -cp . %~n1
)

※ -cpがポイントらしい。

で先にいじった

"cmd": ["javac", "$file_name","&&","java", "$file_base_name"],

ここを

"cmd": ["runJava.bat", "$file_name"],

に書き換えます。もうバッチファイルの中でjavacとjavaを実行してしまうのでこれでよろしいかと。
file-nameはfileでもいいみたい?(うろ覚え)最後に,でつなげるのを忘れずに。

Sublime Text2はUTF-8がデフォなので、Shift-Jisに対応させるためここを参考にしました。

Sublime Text 2」(Windows版)でまずやる2つのこと
http://snickerjp.blogspot.jp/2012/12/sublime-text-2windows2.html

あとから追加して「3つのこと」になったみたいですが、その3つ目がShift-Jisに対応させるというもの。

seanliang/ConvertToUTF8 · GitHub
http://github.com/seanliang/ConvertToUTF8

ここから下ろしてくる。そしてPreferences > Browse Packages > Packagesにそのまま解凍したフォルダを突っ込む。

もしくはまずPackages Controlを導入してからの方法もある。(以下の記事はMac版のようですが)

SublimeText2 で Shift-jis を使う
http://qiita.com/amay077/items/de8688595637d20102c4


で、Ctrl + bでビルド。おりゃ!

だが・・・

Exception in thread "main" java.lang.NumberFormatException: null
	at java.lang.Integer.parseInt(Integer.java:454)
	at java.lang.Integer.parseInt(Integer.java:527)
	at Sample4.main(Sample4.java:15)

まあ2つの数字を入力させて、それをparseInt()で数値に変換し2つの数字を比べる、というプログラムなのですが(詳しくは「やさしいJava」を)
どうしても上記のようなエラーがでる。コマンドプロンプト上では何の問題もないのに。

http://stackoverflow.com/questions/12291058/sublime-text-2-build-system-to-compile-run-java-in-a-new-terminal-command-prom/12291655#12291655

どうやらSublime Text2では下のコンソールでのユーザーの入力を許可していないらしい(それでnullが入ってparseInt()できないのかな?)
しかもテスト環境はMacのようで、Windowsに関しては「テストできないからわからん」みたいなことをおっしゃってやがります。

http://stackoverflow.com/questions/16716645/how-to-compile-and-run-java-programs-that-include-a-import-with-sublime-text-2

同じ悩みを抱えている人がいて、SublimeJavaCompilerをgit cloneして解決したらしい。

http://github.com/psychowico/SublimeJavaCompiler

そ・こ・でWindowsにgitを構成するところからやったのですが、上手くいかんかった。
特に日本語が混ざったファイルだといつまでたってもコンパイルが終わらんw
これは諦めた。

http://www.sublimetext.com/forum/viewtopic.php?f=3&t=4805
Sublime Textのフォーラムにあったのですが、コマンドプロントを開いてそこで実行する方法があったのでそれにしました。
バッチファイル書き換え。
この方法の欠点は実行するたびに新しいウィンドウが開いてしまうこと。しかも /k オプションを使っているので、プログラム実行後もウィンドウが残ってしまう。
いちいち手動で閉じるのもめんどくさいし、開きっぱではどんどん増えてしまうw

そ・こ・で、taskkillを使って閉じてしまおうとしたのですが、まんまだとバッチファイルからはできない!? ここら辺勉強不足ゆえわかりませんが、普通にコマンドプロンプトを開いて、taskkill /? で説明が出るのでちゃんとあるんですよねえ・・・。

なので、startで動かす。その前に、timeoutでwait状態にして60秒間だけ待ってやる。
自分で替えたところの説明としては、実行終了時の %ERRORLEVEL%が0なら、そのままSublime Text上で実行。その他ならコマンドプロンプト開いて実行、という形にしました。

@ECHO OFF
cd %~dp1
ECHO Compiling %~nx1...
IF EXIST %~n1.class (
DEL %~n1.class
)
javac %~nx1
IF EXIST %~n1.class (
ECHO Running %~n1...
java -cp . %~n1
)
IF "%ERRORLEVEL%" == "0" (
ECHO Finished "%ERRORLEVEL%"
) else (
ECHO Error "%ERRORLEVEL%"
IF EXIST %~n1.class (
ECHO Re-Running %~n1...
start cmd /k java -ea %~n1
start /min /wait timeout /t 60
start /min taskkill /im cmd.exe /f
)
)

んで

  • 60秒間たてばtaskkill発動しウィンドウ閉じる。
  • その前にtimeoutの方を閉じ&&プログラムが終了していれば、ウィンドウが閉じる。
  • プログラムがまだ終了していなければ閉じないが、終了したとたんにウィンドウも閉じる。
  • 複数開いていてもちゃんと個別に閉じる。

という風になりました。もっとスマートな方法でできれば良いのだけど、ここが限界でござる。
まあ何かを入力させる、というプログラムは学習しているうちはあんまりないだろうなあ。
【追記】忘れてましたw パッケージ化するとできないw もうちょっと頑張ればなんとかなりそうなんだけど、これで丸3日も費やしてしまったので・・・疲れた。結論としては「コンパイルまでは良いかも知らんけど、実行となると難あり」という感じですかね。