私のPCの中には色んなデータが入っています。 APNGとかSVGとかに手を出してるんで、まぁ色々です。 全部簡単にチェックできればいいんですが、まず全部表示できるようなヴューアが少ないです。 全部表示して整理できるようなソフトとかって、あるんでしょうかね? 作るわけには行かないしなぁ。
で、ふと気付いたのがブラウザ、これは万能ビューアですよね。 APNGでもSVGでも見れますし、音でも動画でもOK。 しかしローカルのファイルをチェックするには使い勝手が良くありません。 「何とか使えないかなぁ」と適当に検索してみたら、ちょっと気になるネタがありました。 「http 簡易サーバ」で検索するとC#でもjavaでもけっこう簡単にhttpのサーバが作れるようなんですよ。 もちろんインターネットに公開するようなサーバーを作るのは簡単ではないでしょうけど、ヴューアの部分をブラウザに頼った「ローカルファイル整理ツール」を作るハードルはかなり下がりそうです。
C#だと「System.Net.HttpListener」が、javaだと「com.sun.net.httpserver.HttpServer」が使えるようですね。 「データ整理ツールを作るんなら環境依存は少ない方がいいだろう」ってことでjavaの方を試してみました。 とりあえず考えながら作ったら、
- サーバはjavaアプリ、クライアントはブラウザ。
- サーバで用意した画像をブラウザで表示。
- サーバで用意したテキストをブラウザで表示。
- htmlでformを書く。htmlをブラウザで開いてformの編集情報をpost、サーバで受け取る。
というようなコードになりました。
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.*;
import java.net.*;
public class JunkContentsBox implements HttpHandler
{
public final static int SERVER_RESPONSE_OK = 200;
public final static int SERVER_PORT = 80;
public final static int SERVER_STOP_DELAY = 10;
private HttpServer _server = null;
private Thread _serverThread = null;
private byte[] _testImage;
public static void main(String[] args)
{
JunkContentsBox thisApp = new JunkContentsBox();
thisApp.run();
}
public void run()
{
readTestImage();
startServer();
WaitEnterKey();
stopServer();
}
public void readTestImage()
{
InputStream in = null;
try
{
URL url = this.getClass().getResource("test.png");
File file = new File(url.getFile());
in = url.openStream();
_testImage = new byte[(int)file.length()];
in.read(_testImage);
}
catch(Exception exc)
{
exc.printStackTrace();
}
finally
{
if(in != null)
{
try
{
in.close();
}catch(Exception exc){}
}
}
}
public void WaitEnterKey()
{
System.out.print("Push enter to stop.\n> ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try
{
br.readLine();
}
catch(Exception exc)
{
exc.printStackTrace();
}
}
public void startServer()
{
System.out.println("Confirm a command : server start");
_serverThread = new Thread()
{
@Override
public void run()
{
try
{
_server = HttpServer.create(new InetSocketAddress(SERVER_PORT), 0);
_server.createContext("/", JunkContentsBox.this);
_server.start();
}
catch (IOException exc)
{
exc.printStackTrace();
}
}
};
_serverThread.start();
System.out.println("Server is started.");
}
public void stopServer()
{
System.out.println("Confirm a command : server stop");
System.out.format("Wait %d seconds...\n", SERVER_STOP_DELAY);
assert _server != null && _serverThread != null;
_server.stop(SERVER_STOP_DELAY);
System.out.println("Server is stopped.");
}
@Override
public void handle(HttpExchange ex) throws IOException
{
OutputStream os = ex.getResponseBody();
try
{
String uri = ex.getRequestURI().toString();
if(uri.equals("/test.png"))
{
ex.getResponseHeaders().add("Content-Type", "image/png");
ex.sendResponseHeaders(SERVER_RESPONSE_OK, _testImage.length);
os.write(_testImage);
}
else
{
ex.getResponseHeaders().add("Content-Type", "text/plain");
String requestBody = getRequestBodyString(ex);
String resTxt = uri + "\n" + requestBody;
byte[] resBuff = resTxt.getBytes();
ex.sendResponseHeaders(SERVER_RESPONSE_OK, resBuff.length);
os.write(resBuff);
}
}
catch(Exception exc)
{
exc.printStackTrace();
}
finally
{
try
{
os.close();
}catch(Exception exc){}
}
}
private String getRequestBodyString(HttpExchange ex)
{
InputStream is = ex.getRequestBody();
try
{
ByteArrayOutputStream requestBuff = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while((len = is.read(buff)) != -1)
{
requestBuff.write(buff, 0, len);
}
return URLDecoder.decode(requestBuff.toString(), "utf-8");
}
catch(Exception exc)
{
exc.printStackTrace();
return "";
}
finally
{
try
{
is.close();
}catch(Exception exc){}
}
}
}
クラス名は「最終的にそんなのができたら良いなぁ」という妄想ですな。 とりあえずコンパイルして、クラスと同じフォルダに適当な「test.png」を用意。 次のhtmlも用意です。
<html>
<head></head>
<body>
<form action="http://localhost/testContext" method="post">
<p>入力1 : <input type="text" name="text1" value="あいうえお" size="20" /></p>
<p>入力2 : <input type="text" name="text2" value="かきこけこさしすせそ" size="20" /></p>
<p>入力3 :
<input type="radio" name="radio1" value="表示1" checked="checked">表示1</input>
<input type="radio" name="radio1" value="表示2" checked="checked">表示2</input>
<input type="radio" name="radio1" value="表示3" checked="checked">表示3</input>
</p>
<p><input type="submit" name="submit" value="送信" /></p>
</form>
<img src="http://localhost/test.png"/>
</body>
</html>
htmlファイルのパスは適当でOK。
コマンドプロンプトで実行したら「なんたらかんたら ... Push enter to stop.」と表示されて止まります。 表のスレッドはenterキー待ち、裏のスレッドでサーバを動かしています。 この状態でブラウザで↑のhtmlを開くとformと「test.png」が表示されます。 formはhtmlの内容なのでローカルファイルをそのまま表示、「test.png」は「src="http://localhost/test.png"」なのでサーバが送った画像が表示されています。 formの送信ボタンを押すとパラメータがpostされてサーバに届きます。 その内容はtext/plainで応答。 htmlにしなかったのは手抜きですけど、まぁ多分htmlにしたらブラウザもそう受け取ってくれていたでしょう。 コマンドプロンプトでenterキーを押したらサーバの停止です。
数時間で作ったコードなんでところどころマズいですね。 って言ったらダメなのか、腕のいい人はパッと作ったものが良品といいますしね。 ちょいと反省。 で、こんな私でも数時間で簡易サーバを作れるってのはいい時代です。
ローカル専用と割り切ってセキュリティをぬるめにすれば「formの情報を元にローカルファイルをガリガリ」とかってのは、「GUIもjavaで全部コーディング」ってのと比べて楽になりそうです。 firewallはちゃんとしないとダメでしょうけど。
あれ? なんか文章が整理ツール作る方に行ってる? 無理ですから。

