Javaで動的に配列を生成するメモ
Javaで任意の型の配列を動的に作る方法を知らない事に気が付いた。
大概は Object[ ] で対処できるので今まで調べたことが無かったっぽい。
結論から言うとこうする。
int[] ary = (int[])java.lang.reflect.Array.newInstance(int.class, 10);
言語仕様上は静的にしか配列の型は決められないので reflect で生成するようになっている。
まぁ、普通使わないよなこんなの...
HTML5のCanvasで点線が書けないなんて...
ブラウザ上でツールを作っていて気が付いたのだが HTML5 の Canvas は点線、破線が書けない。
そんな馬鹿なと思ったが、仕様上持っておらずほんとに書けない。
Webでググるといかにも力技な解決策を教えて貰えます。
- http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvasより。
var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
if (CP.lineTo) {
CP.dashedLine = function(x, y, x2, y2, da) {
if (!da) da = [10,5];
this.save();
var dx = (x2-x), dy = (y2-y);
var len = Math.sqrt(dx*dx + dy*dy);
var rot = Math.atan2(dy, dx);
this.translate(x, y);
this.moveTo(0, 0);
this.rotate(rot);
var dc = da.length;
var di = 0, draw = true;
x = 0;
while (len > x) {
x += da[di++ % dc];
if (x > len) x = len;
draw ? this.lineTo(x, 0): this.moveTo(x, 0);
draw = !draw;
}
this.restore();
}
}
作成中のツールが動的に Canvas を使うものだったのでやりたく無いなー と思ってもう少し調べたら同じページにブラウザ毎の対処方がのってました。
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
if ( ctx.setLineDash !== undefined ) ctx.setLineDash([5,10]);
if ( ctx.mozDash !== undefined ) ctx.mozDash = [5,10];
Chrome は setLineDash()、Firefox は mozDash を使えば行けるようです。
IE は... サポートする気無いからいいや。
点線の書けない 2D 系のAPIなんで初めてみました。早く仕様に取り込んで欲しいものです。
JavaのDateの時刻をリセットするメモ
時間ねたが続くが Java で Date から時刻をリセットして日付だけを取り出そうとしてはまったのでメモ。
日付関係の処理はややこしい。タイムゾーンとか夏時間とか閏秒とか訳分からん。
Java の場合は java.util.Calendar が一手に引き受けてくれるのだが こいつがまた曲者ではまった。
結論だけ欲しい人の為の正解、
static Date clearTime(Date date) {
Calendar cal = new GregorianCalendar();
cal.setTime(date);
cal.clear(Calendar.AM_PM);
cal.clear(Calendar.HOUR);
cal.clear(Calendar.HOUR_OF_DAY);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
return cal.getTime();
}
これで、もろもろの面倒を考えずに日付だけが取り出せる。
単純に考えると
cal.clear(Calendar.HOUR);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
だけで良さそうだがこれだとこうなる。
2013/04/07 14:00:00.000
AM_PMリセットしても
cal.clear(Calendar.AM_PM);
こうだったりする。
2013/04/07 02:00:00.000
結局、AM_PM をクリアしてから HOUR と HOUR_OF_DAY
の両方をクリアする必要があるという謎な仕様。
普通に Calendar.clearTime() が有っても良いと思うんだが...
SQLServerのdatetime型にはまったのでメモ
仕事で Postgre から SQLServer に移植していてはまったのでメモ。
- SQLServer の datetime 型はミリ秒の桁が 0,3,7 に丸められる。
- WHERE句で比較する場合は丸めが起こらないので比較が一致しない。
具体的にどういう時に起こったかと言うと O/R マッパーを使っていて Bean に日付が残っていたケース。
bean.setKey(123);
bean.setUpdateTime(new Date());
ORMapper.insert(bean);
bean.setItem("hogehoge");
ORMapper.update(bean);
とかやった時に O/R マッパーがこんな SQL を生成してた。
INSERT INTO Bean (key,updateTime) VALUES (123,'2013-01-01T00:00:00.999');
ここで updateTime には '2013-01-01T00:00:01.000' が入る。
UPDATE Bean SET item='hogehoge' WHERE key=123 AND updateTime='2013-01-01T00:00:00.999';
WHERE句の updateTime 丸めが起こらないので UPDATE が失敗してしまう。
WHERE updateTime がそもそも不要なので O/R マッパーの設定ファイルの問題なんだけど DB がアプリが指定した物と違う値を書き込むって有りなの?
後、1/3ミリ秒単位って言うのも謎だし。
尚、SQLServer 2008 からは datetime2型が用意されて 100ナノ秒まで持てます。
AndroidでWebServerを動かしてみた。
Android でも普通に ServerSocket が使えると言う話を小耳に挟んだので調べて見ると既に jetty が普通に動いているらしい。
これをインストールして試してもあんまり面白く無いので 自前で簡易WebServerを作ってみた。
ソース:
package org.kotemaru.android.webserver;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends Activity {
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
new AcceptThread(8080).start();
} catch (IOException e) {
postMessage(e.getMessage());
Log.e("boot",e.getMessage());
}
}
void postMessage(final String msg) {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
private class AcceptThread extends Thread {
private ServerSocket ssock;
public AcceptThread(int port) throws IOException {
this.ssock = new ServerSocket(port);
}
@Override
public void run() {
try {
postMessage("Server start");
while (true) {
Socket sock = ssock.accept();
new ConnectThread(sock).start();
}
} catch (IOException e) {
postMessage(e.getMessage());
Log.e("AcceptThread",e.getMessage());
}
}
}
private class ConnectThread extends Thread {
private Socket sock;
public ConnectThread(Socket sock) {
this.sock = sock;
}
@Override
public void run() {
try {
Log.i("ConnectThread","From "+sock.getRemoteSocketAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream());
String reqLine = in.readLine();
String line = in.readLine();
while (!line.isEmpty()) {
line = in.readLine(); // ヘッダーは無視 (^^;
}
String[] parts = reqLine.split(" ");
String path = parts[1].replaceFirst("[?].*$", "");
File docroot = new File(Environment.getExternalStorageDirectory(),"docroot");
out.write("HTTP/1.0 200 OK\r\n".getBytes());
out.write(("Content-type: "+getCType(path)+"\r\n\r\n").getBytes());
InputStream fin = new FileInputStream(new File(docroot,path));
try {
byte[] buff = new byte[1024];
int n;
while ((n=fin.read(buff))>0) {
out.write(buff,0,n);
}
out.flush();
out.close();
} finally {
fin.close();
}
} catch (IOException e) {
postMessage(e.getMessage());
Log.e("ConnectThread",e.getMessage());
} finally {
try {
sock.close();
} catch (IOException e) {
postMessage(e.getMessage());
Log.e("ConnectThread",e.getMessage());
}
}
}
private String getCType(String path) {
path = path.toLowerCase();
if (path.endsWith(".html")) return "text/html";
if (path.endsWith(".jpg")) return "image/jpeg";
if (path.endsWith(".png")) return "image/png";
if (path.endsWith(".gif")) return "image/gif";
if (path.endsWith(".js")) return "application/javascript";
if (path.endsWith(".css")) return "text/css";
return "unknown";
}
}
}
起動が Activity から行われている事以外はほんとにただの WebServer の実装。
DocumentRoot は内部ストレージの「docroot/」としたので コンテンツは Nexus7 をUSBで繋いでPCからコピペすればOK。

Wifi設定で Nexus7 のIPアドレスを調べてブラウザから直接URLを叩くとちゃんと表示された!

尚、AndroidManifest.xml には以下の設定が必要。
<uses-permission android:name="android.permission.INTERNET" />
但し、これを設定しても port=80 のサーバはパーミッションエラーとなる。 たぶん、root権が必要。
...
モバイル用途の端末だとサーバ化はあんまり意味無いっていうかセキュリティ上の問題がありそうだけど、 スティック型Androidの使い道は色々広がりそう。
安定動作しそうな スティック型Android 出ないかなぁ
お花見
今日は、代々木公園で花見でした。

これから行く人は砂埃が凄かったので風向きに注意です。
あと、夕方は予想以上に寒かったので昼に暖かくても上着を持って行きましょう。
スティック型 Android が欲すい...
久々に物欲を刺激する物を発見。
スティック型アンドロイド。
要は通常の Android から液晶を外して変わりに HDMI ポートを付けたもの。
値段も1万未満と玩具として手頃。
Nexus7 は root 取らないと以外に遊べないのだが 普段使いのメールとかを登録してあるので root は取りたく無い。
で、安い Android 無いかなと思って探したらこれが出て来た。
ただ、基本 中華Android なので品質にかなり問題が有る様子...
アマゾンのコメントにはどの商品にもこんなコメントが付いてます。
WiFi設定をして、アカウント登録をして、GooglePlayをクリックしたら、、、画面が緑と黒の横縞になってフリーズ。 せめてYouTubeでもと、アプリをクリックするとシャットダウン。 初期不良でしょうか? 交換を希望しましたができないらしい。対応は返品のみ。 再度購入する勇気はないのでさようならです。
とか
起動しても何も反応がなくすぐに電源が落ちてしまいます最悪です絶対に買わないほうがいいです
とか
オンキョーのが有るので見てみたがこいつは別の意味で評判が悪い。
まあ、ダメ元で買っても良い値段ではあるのだけど既に文珍化した中華Pad を1台所持している身としては買いづらい。
ASCIIの記事 にメーカー製も発売される見たいな事が書いてあるから様子見かなぁ
markdown のサポート
ブログのWiki対応で最初は標準化を謳っている Wiki Creole にしようと思って いたんだけど仕様が曖昧で実装も良さげな物が無い。
で、調べてたら markdown って言う Wiki っぽい仕様が有って Git-HUB でも採用しているらしい。
基本的に元の文書のままでも読める事を前提としている仕様との事。
ちょっと使ってみた感じ。
- 長所:
- 文中にソースコードが埋め込まれる事を考慮している。
- HTMLのタグもそのまま使える。
- 短所:
- テーブルが書けない。(
<table>タグで書く) - 文節内での改行制御ができない(
<br/>タグで書く)
- テーブルが書けない。(
Git-HUB が採用しているだけ有って技術系の文書は非常に書きやすい。
短所は逃げ道が用意して有りどうにもならないと言う状況は無い。
markdown の Java 実装は markdownj と言うのが有った。
置き場所が散らかっていて分かりづらいので整理。
使い方が何処にも書いて無くて困ったのだがソース内のコメントを読んだらこれだけだったw。
MarkdownProcessor markdown = new MarkdownProcessor();
String htmlText = markdown.markdown(markdownText);
記法ざっくりまとめ
ヘッダー
## ヘッダー2
### ヘッダー3
#### ヘッダー4
ヘッダー2
ヘッダー3
ヘッダー4
リスト
- リスト
- ネスト2
- ネスト3
- zzz
- リスト
- ネスト2
- ネスト3
- zzz
リンク各種
- [リンク](http://examle.com)
- <http://examle.com>
- [外部定義リンク][]
[外部定義リンク]: http://examle.com "タイトル"
画像

インライン
- *強調*
- **とても強調**
- `<escape>`
- 強調
- とても強調
<escape>
ソースコード
[xxxx](xxxxx)
<pre>[xxxx](xxxxx)
</pre>
[xxxx](xxxxx)
[xxxx](xxxxx)
引用
> aaaaaa
aaaaaa
区切り線
------------------

