6月 18 2011

Oisixで開催されたJavaの勉強会に行ってきた。

Category: java,勉強会simultechnology @ 5:39 AM

6/17(金)、五反田にあるOisixで行われたJavaの勉強会に参加してきた。

勉強会はちょくちょく参加したりはするけど、自分が参加するほとんどが実際にコーディングするようなハンズオン形式だったりもくもく的な勉強会なので、今日のようなプレゼン形式の勉強会は新鮮に感じた。

以下は勉強会の募集のurl。
http://atnd.org/events/16678

More »

内容はOisixの3名の方が発表された。

最初はスズケンさんの発表。
主にUIについて。自分は業務アプリばかりなので、やっぱりOisixのような一般ユーザ対象のシステムってUIが大事だよなぁって改めて思った。
Oisixはユーザビリティにかなり拘りがあるようだ。JSPで未だにjstlタグなどよく使っているが、jstlは遅いとのこと。

2人目はフカワさんの発表。
YahooリスティングサービスやGoogle Analyticsとの連携など。Google Analytics使ってみようかな、と思った。ExcelでGoogle Analyticsのアドオンがあるのには驚いた。

最後はヤマシタさんの発表。
創業から、どんなアーキテクチャやフレームワークを使ってきたかのお話。自分も馴染みのあるフレームワークの話があったり、ちょっと会社の歴史を感じたりで面白かった。
Struts2はかなり出来の良いフレームワークとのこと。またjspの式言語であるOGNLは非常に強力とのこと。

最近のJavaの勉強会というと、クラウドとかandroidなどが多い印象があって、今回のようなオーソドックスなJavaのWebアプリの話など逆に新鮮に感じた。Javaでこういうスタンスの勉強会はけっこう貴重だなと個人的には思う。

発表の後は懇親会。
Oisixの方が用意してくれた料理は、さすが食品を扱っている会社だけあってメチャメチャ美味しかった。

最後はお土産までいただきました。

Oisixの方々、本当にありがとうございました。



6月 17 2011

eclipseとgithubを連携する。

Category: eclipse,gitsimultechnology @ 3:34 PM

今までプライベートのバージョン管理はGoogleのsvnを使っていたけれど、最近githubを少し使い始めた。「入門git」を読みながら少しずつやってる感じだけど、操作はターミナルからコマンドを打つ感じ。

自分がプライベートでコード書く場合はほとんどeclipse使っているから、やっぱりeclipseから操作したいと思った。その時のメモ。ちなみにOSはubuntu10.10。

More »

まずは当然だけど、gitのインストール。

>sudo apt-get install git

インストールしたら最初に名前とメールアドレスを登録した方がよい。コミットのログに残るため。

>git config --global user.name "simultechnology"
>git config --global user.email "tissi0708@gmail.com"

設定値は次のコマンドで確認できる。

>git config --global --list

user.name=simultechnology
user.email=tissi0708@gmail.com

また以下のコマンドを打つと、以下のようにターミナルで色分けしてくれる。

>git config --global color.ui "auto"

次に適当な箇所にフォルダを作り、ファイルを追加、自分のリモートリポジトリにコミットまで行う。

>mkdir test_directory
>cd test_directory
>vi hoge.txt
>git add hoge.txt
>git commit -m 'first-commit'

コミットされているかどうか等、現在の状態を確認するには以下。

>git status

またログを確認するには以下のコマンド。

>git log

githubでリポジトリーを作成すると、以下のような画面になるので、表示されているurlをコピーする。

上でコピーしたのはgithub上のリポジトリ。このリモートリポジトリを自分のローカルマシンに”origin”という別名で追加する。ちなみに”origin”はローカルに割り当てられるデフォルトのリモートリポジトリ名。これでローカルリポジトリとリモートリポジトリを同期できるようになる。

>git remote add origin git@github.com:simultechnology/test.git

ここで、ローカルのコミット分をリモートに反映(push)しようとするとエラーになる。。

>git push origin master

The authenticity of host 'github.com (207.97.227.239)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,207.97.227.239' (RSA) to the list of known hosts.
Permission denied (publickey).
fatal: The remote end hung up unexpectedly

githubの認証にはssh公開鍵というものが必要で、これを自分のマシンで作成しないといけない。
githubにその手順が乗っている。以下はlinux用のurl。windowsやmacもある。
http://help.github.com/linux-set-up-git/

公開鍵の作成が無事に終わるとgithubにpushできるようになる。ここからeclipseを使用する。

まずgitプラグインである「egit」をインストールする。
Eclipseマーケットプレイスからインストールするのが一番楽だと思う。

eclipseでプロジェクトを作成する。

作成したプロジェクト上で右クリックすると、「チーム」が表示されるので選択すると「プロジェクトの共用」が表示されるので、選択すると以下のダイアログが表示される。「Git」を選択し「次へ」を押す。

Gitリポジトリーの構成という画面が表示される。プロジェクトを選択すると、「リポジトリーの作成」ボタンが押せるようになるので押す。

作成したリポジトリが表示される。その後、「完了」を押す。

メニューの「ウィンドウ」→「ビューの表示」→「Git」→「Gitリポジトリ」を選択すると、作成したリポジトリが表示される。

プロジェクトエクスプローラ等でファイルを見ると、バージョン管理がされていないものははてなマークが表示される。
右クリックで「チーム」を選択すると、Gitのメニューが表示される。この辺のインターフェースはsvitnプラグインのsubversiveとよく似ているので、eclipseでsvnを使った事があればわかりやすいと思う。

Gitのメニューから「同期化」を押すと以下のダイアログが表示されるので「OK」。

ファイルを選択すると、以前のファイルとの差分を表示してくれる比較エディタが表示される。変更箇所とか確かめたい時には便利。

コミットしたいファイルもしくはフォルダを選択し、右クリック→「チーム」→「コミット」で以下のコミットを促すダイアログが表示される。コミットしたいファイルを選択する。またコメントも追加し、「コミット」ボタンを押す。

この状態でローカルリポジトリにコミットされた状態になる。プロジェクト上で右クリック→「チーム」→「ヒストリーに表示」で、コメントや作成者などのログが表示される。非常に見やすい。

あとは、githubにpushするだけ…なんだけれど、ここまではeclipseでスムーズにできたけど、eclipseでpushしようとするとどうも上手くいかない。やり方が間違っているのかもしれないけど、何度も試したけど駄目だった。

という訳で最後のリモートリポジトリにpushだけはターミナルでコマンドをたたいて行う。

ターミナルを立ち上げ、eclipseで作成したプロジェクトのルートファルダに移動する。念のためにlogなどが反映されているかどうか確認などしてみる。

>cd gae-csv-upload/
>git log

commit 38a682d・・
Author: simultechnology 
Date:   Fri Jun 17 14:53:16 2011 +0900

    新規プロジェクト作成

ちゃんとログが表示される。

githubのリモートリポジトリをローカルに作成し、pushする。

>git remote add origin git@github.com:simultechnology/gae-csv-upload.git
> git push origin master

すると、以下のようなポップアップが表示され、パスワードを求められる。公開鍵を作成した時に登録したパスワードを入力する。

以下のようなログが表示され、無事にgithubにpushされる。

Counting objects: 59, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (52/52), done.
Writing objects: 100% (59/59), 8.03 MiB | 700 KiB/s, done.
Total 59 (delta 0), reused 0 (delta 0)
To git@github.com:simultechnology/gae-csv-upload.git
 * [new branch]      master -> master

githubの画面を確認すると、ソースが反映されていることが確認できる。ちなみに今回、作成したリポジトリは以下。

https://github.com/simultechnology/gae-csv-upload



6月 03 2011

始めてAndroid Marketにアップしてみた。

Category: android,javasimultechnology @ 2:13 AM

最近、Androidを触ることが増えてきたので、超ショボくてチョベリバって感じだけど、作ったものをAndroid Markertに登録してみた。

urlは以下。
https://market.android.com/details?id=relation.word&feature=search_result

More »

Marketの説明にも書いているけど、データの取得元は『はてなキーワード連想語API』。アプリの中身は、入力された単語をパラメータとしてAPIにリクエストを投げ、そのレスポンスを解析している表示している、といった単純なアプリ、、
なのだが、APIの呼出しのところでちょっとハマった。

APIの呼出しのプロトコルはXML-RPCなので、最初、Apache XML-RPCを使用して書いた。単純なJavaプロジェクトから起動させた時は問題なく動作した。

その時に参考にさせてもらったサイトはこちら

http://blog.livedoor.jp/ryu22e/archives/65114867.html

当初、Javaプロジェクトで動作したコードをandroidプロジェクトでも使用すれば大丈夫かな、と単純に思っていた。

でもデータが表示されない。中を見てみると、以下のようなエラーが出ていた。

org.apache.xmlrpc.XmlRpcException: Unable to create XML parser:org.xml.sax.SAXNotRecognizedException: http://xml.org/sax/features/external-parameter-entities

デバッグしてみると、どうもjarに含まれているSAXparserクラスで出てるみたいなので、自分ではどうにもならず、他のモジュールを探すことにした。

そこで見つけたのが以下のandroid用のモジュール。
http://code.google.com/p/android-xmlrpc/

これだととりあえず上手くいった。以下はAPI呼出し部分のコード

		XMLRPCClient client = new XMLRPCClient("http://d.hatena.ne.jp/xmlrpc");

		// リクエストに含めるパラメータの設定
		Map param = new HashMap();
		// "android"をパラメータとする
		param.put("wordlist", "android");

		Object result = null;
		try {
			// RPCをコールする
			result = (Object) client.call("hatena.getSimilarWord", param);
		} catch (XMLRPCException e) {
			e.printStackTrace();
		}

		// APIからの取得
		Object[] arrayWord = (Object[]) ((Map) result).get("wordlist");

ただ、上記の場合パラメータが”android”で半角英字なので上手くいくが、パラメータに日本語を指定するとデータが取得できない。

なので文字コードをUTF-8に指定したら無事に上手くいった。


タグ:


3月 16 2011

javaで複数のエクセルファイルをgrepのように検索する。

Category: javasimultechnology @ 1:36 AM

あるキーワードを検索する時によくgrepを使うけど、テキストファイルに対してしか有効ではない。エクセルも一応、検索してくれるけど、かなり文字化けとかしててグッチャグッチャになって当然だけど使えない。

複数のエクセルファイルをgrepするツールもあるみたいだけど、仕事でjavaからエクセルを扱うpoiというライブラリを最近、使ったこともあって、javaで書いてみようと思った。

More »

poiは以下からダウンロードできる。
http://poi.apache.org/download.html

また、最近のエクセルファイルの拡張子は「.xlsx」で、エクセル2003までの「.xls」と違っているらしい。エクセルって基本的に仕事でしか使わないし、古いエクセル使っているから知らなかった。自分のマシンのエクセルを使って初めて知った。まぁ、だいたいの開発現場ってそんなに新しいバージョンのofficeなんて使わないだろうから、知らなくても当然だよね(汗)

ちなみに、その「.xlsx」ファイルを扱うには、上記のpoiだけでは足りなくて、以下のapache xmlbeansというライブラリが必要だった。

http://xmlbeans.apache.org/sourceAndBinaries/index.html

あと以下は使っても使わなくてもいいけど、空文字チェックなどで、apache Commons Langという有名なライブラリを使った。(今回は空文字チェックだけなので、使う必要もなかったけど)

http://commons.apache.org/lang/download_lang.cgi

プロジェクト構成はこんな感じ。

以下がコード。ちょっと長くなってしまったけど。
Main.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.InputStream;
import java.util.Scanner;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class Main {

	public static void main(String[] args) throws Exception {
		Scanner stdIn = new Scanner(System.in, "SJIS");

		System.out.println("Excelファイルをgrepして検索します。");
		System.out.println("検索対象の単語と検索したいディレクトリパスを指定していただきます。");
		System.out.println("まず検索対象の単語を入力して下さい。");

		// 検索したい単語
		String word = null;
		while (StringUtils.isEmpty(word)) {
			word = stdIn.next();
			if (StringUtils.isEmpty(word)) {
				System.out.println("再度、検索対象の単語を入力して下さい。");
				continue;
			}
			else {
				break;
			}
		}

		System.out.println("続いて検索したいディレクトリパスをを入力して下さい。");
		// ディレクトリのパス
		String directoryPath = null;
		while (StringUtils.isEmpty(directoryPath)) {
			directoryPath = stdIn.next();
			if (StringUtils.isEmpty(directoryPath)) {
				System.out.println("再度、検索したいディレクトリパスを入力して下さい。");
				continue;
			}
			else {
				break;
			}
		}
		// 検索の実行
		searchDir(word, directoryPath);

	}

	/**
	 *

引数で渡されたディレクトリ以下を再帰的に検索する。

	 *
	 * @param path ディレクトリパス
	 * @return
	 * @throws Exception
	 */
	private static boolean searchDir(final String word, String path) throws Exception {
		File file = new File(path);
		File[] listFiles = file.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {
				// ドットで始まるファイルは対象外
				if (name.startsWith(".")) {
					return false;
				}
				// 対象要素の絶対パスを取得
				String absolutePath = dir.getAbsolutePath()
										+ File.separator + name;
				// エクセルファイルのみ対象とする。
				if (new File(absolutePath).isFile()
					&& (absolutePath.endsWith(".xls")
						|| absolutePath.endsWith(".xlsx"))) {
						return true;
				}
				else {
					// ディレクトリの場合、再び同一メソッドを呼出す。
					try {
						return searchDir(word, absolutePath);
					} catch (Exception e) {
						//e.printStackTrace();
						// エラーが出た場合falseを返す。
						return false;
					}
				}
			}
		});

		if (listFiles == null) {
			return false;
		}

		for (File f : listFiles) {
			if (f.isFile()) {
				searchWord(word, f);
			}
		}
		return true;
	}

    /**
     *

ファイルから単語を検索し、その単語が含まれるセルの値を表示する。

     *
     * @param word 検索対象の単語
     * @param file 検索対象ファイル
     * @throws Exception
     */
	private static void searchWord(String word, File file) throws Exception {
		// Excelファイルの読込み
		InputStream in1 = new FileInputStream(file);
		Workbook wb1;
		try {
			wb1 = WorkbookFactory.create(in1);
		} catch (Exception ex) {
			return;
		}

		// シート枚数を読込み
		int numberOfSheets = wb1.getNumberOfSheets();
		// シート枚数分ループ処理
		for (int i = 0; i < numberOfSheets; i++) {
			StringBuilder sb = new StringBuilder();
			// シート
			Sheet sheet = wb1.getSheetAt(i);
			// シート名
			String sheetName = sheet.getSheetName();
			// シートの最終行
			int lastRowNum = sheet.getLastRowNum();
			// 最終行までループ処理
			for (int j = 0; j <= lastRowNum; j++) {
				// 行の取得
				Row row = sheet.getRow(j);
				if (row != null) {
					// 行内の最後のセルの位置
					short lastCellNum = row.getLastCellNum();
					// 行内の最後のセルまでループ処理
					for (int k = 0; k < lastCellNum; k++) {
						// セルを取得
						Cell cell = row.getCell(k);
						if (cell != null) {
							// セルのタイプを取得
							int cellType = cell.getCellType();
							// セルの値が文字列の場合
							if (cellType == Cell.CELL_TYPE_STRING) {
								if (cell.getStringCellValue().contains(word)) {
									sb = appendRecord(sb,
													  file.getAbsolutePath(),
													  sheetName,
													  convertCellPos(j, k),
													  cell.getStringCellValue());
								}
							}
							// セルの値が数値の場合
							else if (cellType == Cell.CELL_TYPE_NUMERIC) {
								if (String.valueOf(cell.getNumericCellValue()).contains(word)) {
									sb = appendRecord(sb,
													  file.getAbsolutePath(),
													  sheetName,
													  convertCellPos(j, k),
													  String.valueOf(cell.getNumericCellValue()));
								}
							}
						}
					}
					if (sb.length() > 0 && !sb.toString().endsWith("\n")) {
						sb.append("\n");
					}
				}
			}
			System.out.print(sb.toString());
		}
	}

    /**
     *

文字列バッファにファイルパス、シート名、セルの位置情報、値を設定して返却する。

     *
     * @param sb 文字列バッファ
     * @param filePath ファイルパス
     * @param sheetName シート名
     * @param pos セルの位置情報
     * @param cellValue セルの値
     * @return sb 情報設定後の文字列バッファ
     */
	private static StringBuilder appendRecord(StringBuilder sb,
											  String filePath,
											  String sheetName,
											  String pos,
											  String cellValue) {
		sb.append(filePath);
		sb.append("\t");
		sb.append(sheetName);
		sb.append("\t");
		sb.append(pos);
		sb.append("\t");
		sb.append(cellValue);

		return sb;
	}

    /**
     *

セルの位置情報を返す。

     *


     * 引数の行番号とカラム番号から、セルの位置情報を特定し返却する。
     * 例えば左上のセルは"A1"となる。
     * 

     * @param rowNum (0から始まる)行番号
     * @param colNum (0から始まる)カラム番号
     * @return セルを位置を表す文字列
     * @throws Exception
     */
	private static String convertCellPos(int rowNum, int colNum) throws Exception {
		// カラムを表すアルファベットの配列を生成
		final char[] charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
		final int charSize = charArray.length;
		// オフセットを取得
		int offset = colNum / charSize;

		String cellPos = "";
		if (offset == 0) {
			cellPos = String.valueOf(charArray[colNum]);
		}
		else if (offset < charSize) {
			cellPos = String.valueOf(charArray[offset - 1])
						+ String.valueOf(charArray[colNum - charSize * offset]);
		}
		else {
			throw new Exception("範囲外のセルが指定されています。");
		}
		return String.format("%s%d", cellPos, rowNum + 1);
	}
}

このままでeclipseから実行できるけど、コマンドからも実行したかったかので、jarにして実行しようと思った。jarファイルの場合、manifestファイルに実行のメインクラスとクラスパスを指定できる。

以下のようにマニフェストファイルを指定した。

Class-Path: .
            lib/dom4j-1.7-20060614.jar
            lib/jsr173_1.0_api.jar
            lib/poi-3.8-beta1-20110307.jar
            lib/poi-excelant-3.8-beta1-20110307.jar
            lib/poi-ooxml-3.8-beta1-20110307.jar
            lib/poi-ooxml-schemas-3.8-beta1-20110307.jar
            lib/poi-scratchpad-3.8-beta1-20110307.jar
            lib/resolver.jar xbean.jar
            lib/xbean_xpath.jar
            lib/xmlbeans-qname.jar
            lib/xbean.jar
            lib/xmlpublic.jar
            lib/commons-lang-2.6.jar
Main-Class: Main

クラスパスは、実行するクラスから相対パスで指定しているので、実行するjarファイルと同じフォルダにlibフォルダが存在し、その中に必要なjarファイルが存在する構成となる。
こんな感じ。

jarファイル内に必要なjarファイルを含めようかと思ったけど、それはできないみたいだった。

以下のantスクリプトで、プロジェクト内にjarフォルダを作り、その中にjarファイルを作成するようにした。
build.xml

<?xml version="1.0"?>
<project name="java" default="main">
	<property name="lib" location="lib" />
	<property name="src" location="src" />
	<property name="output" location="classes" />
	<property name="jar" location="jar" />
	<property name="jar.lib" location="${jar}/lib" />

	<target name="main" depends="clean, init, compile, compress" description="Main target">
		<echo>
			Building jar file.
		</echo>
	</target>

	<target name="init">
		<mkdir dir="${output}"/>
        <mkdir dir="${jar}" />
        <mkdir dir="${jar.lib}" />
	</target>

	<target name="compile" description="Compilation target">
	    <javac encoding="SJIS"
	    	   srcdir="${src}"
	    	   destdir="${output}" >
	    	<include name="Main.java" />
	        <classpath>
	           <pathelement path="${classpath}"/>
	           <fileset dir="lib">
	             <include name="**/*.jar"/>
	           </fileset>
	        </classpath>
	    </javac>
	</target>

    <target name="compress" depends="copy" description="Compression target">
        <jar destfile="jar/java.jar"
              manifest="manifest.mf" >
            <fileset dir="${output}" includes="**/*.class" />
        </jar>
    </target>

    <target name="copy" description="Copy jar library">
        <copy todir="${jar.lib}">
            <fileset dir="lib" />
        </copy>
    </target>

	<target name="clean">
		<delete dir="${output}" />
		<delete dir="${jar}" />
	    <delete dir="${jar.lib}" />
	</target>

</project>

build.xmlが存在するディレクトリに移動しantとコマンドラインに入力するとjarファイルが作成される。

以下のようにコマンドを叩くと、探したい言葉が存在するファイル、シート名、セルの位置(A1など)の一覧が出力される。
以下は「イタリア」という言葉があるエクセルファイルを抽出する。

>ant
>cd  jar
jar>java -jar java.jar
Excelファイルをgrepして検索します。
検索対象の単語と検索したいディレクトリパスを指定していただきます。
まず検索対象の単語を入力して下さい。
イタリア
続いて検索したいディレクトリパスをを入力して下さい。
C:\my_work
C:\my_work\testes\test\test.xls 概要    A3      イタリアについて
C:\my_work\testes\test\test.xls 概要    B5      イタリアサッカーについて
C:\my_work\testes\test\test.xls 概要    B7      イタリアサッカーの魅力とは
C:\my_work\testes\at.xlsx       Sheet2  BD117   イタリア
C:\my_work\testes\at.xlsx       Sheet4  GX22    イタリア
C:\my_work\messi.xls    メッシについて  A3      アルゼンチンのロサリオにて、工場労働者の父とパートタイムの清掃員である母
の間に生まれた[1][2][3]。父方の祖先アンジェロ・メッシはイタリアのアンコーナ出身であり、1883年にアルゼンチンに移住した[4]
[5][3] 。5歳の時には父親がコーチを務めるクラブで本格的にサッカーを始め、1995年には地元のクラブであるニューウェルズ・オー
ルドボーイズに入団する。しかし11歳の時に成長ホルモンの分泌異常の症状(低身長)が発覚、治療なしでは身体が発達しないと診断さ
れ、サッカー選手としての未来に暗雲が立ち込める。その頃からその才能には高い評価が与えられておりアルゼンチンの名門クラブで
あるリーベル・プレートが獲得を検討していたが、クラブの事情により治療費が工面できず断念している。

実際には以下のような感じになる。

ソースコードとライブラリは以下にアップした。ただソースはwindowsで動かしたのでsjisだから、ブラウザで見ると文字化けするかも。
http://code.google.com/p/simultechnology/source/browse/trunk/simultechnology/java/



3月 15 2011

javaでディレクトリを再帰的に検索する

Category: javasimultechnology @ 11:11 PM

rubyのDir.glob()やpythonのos.walk()のように、あるディレクトリ以下に含まれるファイルを再帰的に検索するような機能をjavaで書く必要があったので、書いた。

java.io.FileクラスにlistFilesというメソッドがあって、これはディレクトリに含まれるファイル、ディレクトリなどを配列で返す。

More »

再帰的にファイルの一覧を出力するには、ファイルの場合はファイルパスを出力し、ディレクトリの場合は再帰的に自身のメソッドで再びディレクトリを検索することで実現できる。

また、listFilesの引数にはフィルタを渡すこともできて、配列として返したいファイルの条件を指定することもできる。今回はjava,jsp等のソースの一覧を出力させたかったので、隠しファイル(.ドットで始まる)やclassファイルを除外するようにした。

以下がそのコード。
SearchDirectory.java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;

public class SearchDirectory {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		searchDir(args[0]);
	}

	/**
	 * 引数で渡されたディレクトリ以下を再帰的に検索します。
	 *
	 * @param path ディレクトリパス
	 * @return
	 */
	private static boolean searchDir(String path) {
		File file = new File(path);

		File[] listFiles = file.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {
				// ドットで始まるファイルは対象外
				if (name.startsWith(".")) {
					return false;
				}
				// クラスファイルは対象外
				if (name.endsWith(".class")) {
					return false;
				}
				// 対象要素の絶対パスを取得
				String absolutePath = dir.getAbsolutePath()
										+ File.separator + name;
				if (new File(absolutePath).isFile()) {
					return true;
				}
				else {
					// ディレクトリの場合、再び同一メソッドを呼出す。
					return searchDir(absolutePath);
				}
			}
		});

		for (File f : listFiles) {
			if (f.isFile()) {
				System.out.println(f.getAbsolutePath());
			}
		}
		return true;
	}
}

引数にディレクトリ名を指定し実行すると、以下のようにファイル一覧が出力される。

C:\my_work\lib\test.xls
C:\my_work\lib\xbean.jar
C:\my_work\lib\xmlpublic.jar
C:\my_work\testes\test\test.xls
C:\my_work\testes\at.xls
C:\my_work\testes\at.xlsx
C:\my_work\testes\~$at.xlsx
C:\my_work\messi.xls

一つ難を言うなら、ファイルの一覧すべてをメモリに読込むこと。ファイルを一つずつ読込んで出力するように書き直したいけど、それにはpythonのジェネレータがやっぱり理想的かな。。




12月 12 2010

Windowsでrails3.0をMongrelで動かす

Category: rails,rubysimultechnology @ 3:30 AM

開発に関して、滅多にWindowsは使わないんだけど、ちょっとパワーポイントファイルを触らなければいけない事をやっていて、それで以前のノートPCを引っ張り出し、Windows Vistaで開発環境を整えた。

Guiとしてjavaのswingを使っているんだけど、一応、UIとしてブラウザ版もあった方がいいかなと思い、Webアプリを作成することに。。

More »

選択肢はいっぱいあると思うんだけど、短時間でサクッといくなら、やっぱりrailsでしょ?てな訳で、railsを動かし中。

ruby1.92をインストールし、gemでrailsをインストールしようとしたら、幾つかdllファイルが無いと警告を受けた。まぁ、それらはgoogleったらすぐ見つかって、サーバも起動した。

ただ、サーバはデフォルトでは、Webrickなので、mongrelにしようと思い、gemでインストール。その時のmongrelのバージョンは1.1.5。

作成したrailsのプロジェクトの一番上の階層にあるGemfileに、gem ‘mongrel’と記入し、再度サーバを起動。

そしたら、「msvcrt-ruby18.dllが見つかりません」といった感じのエラーが出た。何やら、mongrel1.1.5はruby1.8用のモジュールが必要のようで、ruby1.9環境では互換性が無いらしい。。

解決策はプレリリースのmongrelをインストールすればいいらしい。
以下、コマンド

$gem install mongrel --pre

これでインストールされる。インストールされているmongelの一覧を見る。

$gem list mongrel
>mongrel (1.2.0.pre2 x86-mswin32, 1.1.5 x86-mswin32-60)

Gemfileに、以下のように記述。

gem  'mongrel', '>= 1.2.0.pre2'

これで、以下のように無事に起動した!

>rails s
=> Booting Mongrel
=> Rails 3.0.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server

久々にBeatlesの「All my loving」が聞きたくなって、youtubeでポール・マッカートニー all my loving で検索したら、2008年にケベックでやったっぽいライブの映像が沢山出てきて、すごく良いと思った。
小さい子供までが口ずさんでてちょっと感動。音楽のことは良く分からないけど、やっぱりポールマッカートニーって、ベートーベンやモーツアルト、バッハに匹敵する音楽家なんだろうねぇ。小室哲也はそこには入らないかな?




12月 02 2010

auのAndroidスマートフォン「IS03」をUbuntuで動かした。

Category: androidsimultechnology @ 11:17 PM

先日、auのandroid、「IS03」を購入してしまった。もうかれこれ10年近く、auを使っているので、auのandroidを買えて良かったと素直に思った。

More »

去年のandroidのためだけに購入したdocomoの「HT03」はもう使う事はないと思い、当初、解約しようとしたけれど、2年以内に解約すると違約金が発生してしまう。。なので、docomoについては、一番、料金の安いプランに変更し(月々780円)、2年を過ぎたら、解約する事にした。

さっそくeclipseで動かそうと思ったら、実機では当初なかなか動かなくて困った。ドライバもなさそうだし。。。
windowsでは以下のページからドライバをインストールしたら、android本体に表示された。
http://k-tai.sharp.co.jp/support/a/is03/download/usb/index.html

ubuntuで「IS01」を動かしている人の情報など調べ、以下のサイトの通りに行ったらubuntuからでも無事にandroid本体に表示された。
Ubuntu10.10のeclipseからIS01を認識させる

あと画面のスナップショットをとるのは以下のblogを参考にさせていただいた。
IS01 のスクリーンショットと壁紙

以下がスナップショット。

う~ん、綺麗でテンションが上がる。「HT03」時代は開発しようという気にはなれなかったけど、これならやる気が出そうだ。3日坊主にならなければいいけど。。




11月 23 2010

複数の言葉をまとめて、pythonでgrepする。

Category: pythonsimultechnology @ 4:32 PM

100個くらいの言葉をgrepしなければならなくなったのだけれど、一つずつ行うのは面倒だと思った。
でも、なかなか良いアイデアが思い浮かばなかったので、pythonで書いてみた。

More »

multi_grep.py

# -*- coding: utf-8 -*-
import os
import sys

def file_dump(word_list, path):
	'''word_list内の単語がpathで指定されたファイル内に含まれているか検索し、含まれている場合は行ごと出力する。リストは改行区切りであること'''
	file_obj = file(path, 'rU')
	file_data_list = [line for line in file_obj]
	for w in word_list:
		new_list = [file_line for file_line in file_data_list if w in file_line]
		if len(new_list):
			print file_path
			print "検索対象 : ", w
			for nl in new_list:
				print nl.rstrip()
			print "対象件数 : ", len(new_list)

if __name__=='__main__':
	args = sys.argv
	length = len(args)
	if length < 2 or 3 < length:
		print "引数は1つ、もしくは2つ指定してください。"
		sys.exit(2)
	path1 = args[1]
	# 検索対象ディレクトリが引数で指定されない場合は、カレントディレクトリを検索する
	if length == 2:
		path2 = os.getcwd()
	else:
		path2 = args[2]
	#grep対象のリストファイルを開く
	list_file = file(path1, 'rU')
	word_list = [word.strip() for word in list_file if len(word.strip())]
	list_file.close()
	if os.path.isfile(path2):
		file_path = os.path.join(os.getcwd(), path2)
		file_dump(word_list, file_path)
	else:
		for dirpath, dirs, files in os.walk(path2):
			for each_file in files:
				file_path = os.path.join(dirpath, each_file)
				file_dump(word_list, file_path)

実行は以下。第一引数に検索したい単語のリスト、第二引数に検索したいディレクトリを指定する。

#カレントディレクトリを検索する場合
$ python multi_grep.py word_list




10月 11 2010

Chromeでヘッダー情報を見るメモ

Category: javascriptsimultechnology @ 1:33 PM

Firefoxではうまく動作するのに、Chromeではうまく動作しないものがあったので、ヘッダー情報を確認したいと思った。

Firefoxではアドオンの「Live HTTP Headers」で、ばっちり見れるので、Chromeのエクステンションなどで、同じようなものが無いか探してみた。

More »

結論から言うと、ないっぽい(探し方が不十分なのかも)。

調べたら、以下のJavascriptで、ヘッダー情報をalertで表示させることができる。

(function(){
    function read(url){
        var req = new XMLHttpRequest();
        req.open('HEAD', url, false);
        req.send(null);
        return req.getAllResponseHeaders();
    }
    alert(read(window.location))
})();

「Live HTTP Headers」見れる情報より、かなり少ないが表示はされる。
上のjavascriptでは、もちろんChromeだけじゃなく、他のブラウザでもアラートが表示される。




10月 04 2010

jQueryとsinatraを使ったアプリケーションをGoogle App Engineに乗せた。

Category: google app engine,javascript,jQuery,rubysimultechnology @ 12:14 AM

html5の本をサンプルをやりながら改造して、辞書のAPIからデータを取得し、表示させるというようなシンプルなものを作ってみた。

まず作成し、google app engine上にアップしたのはこれ↓
http://simul-technology.appspot.com

More »

使用したAPIは「イースト辞書Webサービス」。urlはこれ↓
http://www.btonic.com/ws/

html5のcontenteditable属性をtrueにした入力欄に、入力された値をjQueryの$.getJSONメソッドを使用し、非同期でサーバサイドに入力値を送る。
サーバサイドであるsinatra上では、入力値に基づくデータを取得し、それをjson形式でクライアント側に返すような感じ。

まず、フォルダ構成などは以下のようになった。

まず、sinatraのviewであるmyapp/views/index.erbは以下。
myapp/views/index.erb

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>My App</title>
    <script type="text/javascript" charset="utf-8" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js">
    </script>
    <style type="text/css" media="screen">
      body {
          text-align: left;
      }

      ul {
          list-style: none;
      }

      li {
          clear: both;
      }

      li > b, li > span {
          display: block;
          float: left;
          width: 100px;
      }

      li > span {
          width: 500px;
          margin-left: 20px;
      }

      li > span[contenteditable = true]:hover {
          background-color: #ffc;
      }

      li > span[contenteditable = true]:focus {
          background-color: #ffa;
          border: 1px shaded #000;
      }

			article {
				font-size: 0.8em;
			}

      article#main {
          float: left;
      }

      article#main div {
          margin-left: 38px;
      }

      header#input {
          margin-bottom: 60px;
      }

      ul#status li {
          font-size: 0.9em;
      }
    </style>
  </head>
  <body id="forms">
    <h2>Translation Service</h2>
    <h3>My Web App Test by using html5, sinatra, jquery, google app engine, etc.</h3>
    <section>
    <article id="main">
      <header id="input">
        <ul>
          <li>
            <b>検索単語 : </b>
            <span id="en_ja1" contenteditable="true">sample</span>
          </li>
        </ul>
      </header>
			<br />
      <hr />
      <p>
        検索結果
      </p>
      <ul id="exact">
      </ul>
      <hr/>
      <p>
        類似単語検索結果
      </p>
      <ul id="start_with">
      </ul>
    </article>
    <section>
    <script type="text/javascript">

      $(function(){
          getData();
          $("span#en_ja1").focus();
      });

      $(function(){
          $("span[contenteditable=true]").keyup(getData);
      });

      var getData = function(){
          var value = $("#en_ja1").text();

          var getJsonData = function(path, element, match){
              $.getJSON(path, {
                  key: value,
									   match_key: match,
              }, function(data){
                  var retWord = "";
                  element.children().remove();
                  for (original_word in data) {
                      var retWord = original_word + " : " + data[original_word];
                      var textObj = document.createTextNode(retWord);
                      var newLi = document.createElement("li");
                      newLi.appendChild(textObj);
                      element.append(newLi);
                  }
              });
          }

          var exact = $("#exact");
          getJsonData("/translate", exact, "EXACT");

          var start_with = $("#start_with");
          getJsonData("/translate", start_with, "STARTWITH");

      };
    </script>
  </body>
</html>

次はsinatra上で、リクエストを扱い、レスポンスを返す、rubyファイル。myapp/html5_server.rb

# -*- coding: utf-8 -*-
require 'rubygems'
require 'sinatra'
require 'erb'
require 'net/http'
require 'rexml/document'
require 'json'

get "/translate" do
  text = ""
  if request.xhr?
    text = URI.escape(params[:key])
    match = URI.escape(params[:match_key])
    if match == "EXACT"
      page_size = 1
    elsif match == "STARTWITH"
      page_size = 20
    end
    h = Net::HTTP.new("btonic.est.co.jp")
    response = h.get("/NetDic/NetDicV09.asmx/SearchDicItemLite?Dic=EJdict&Word=#{text}&Scope=HEADWORD&Match=#{match}&Merge=AND&Prof=XHTML&PageSize=#{page_size}&PageIndex=0")
    map = {};
    if response.message == 'OK' || response.message == ':HTTPOK'
      document = REXML::Document.new(response.body)
      document.elements['SearchDicItemResult/TitleList'].each_element do |s|
        if s != nil && s.get_elements('ItemID') != nil && s.get_elements('ItemID')[0] != nil
          item_id = s.get_elements('ItemID')[0].get_text.value
          res = h.get("/NetDic/NetDicV09.asmx/GetDicItemLite?Dic=EJdict&Item=#{item_id}&Loc=&Prof=XHTML")
          if res.message == 'OK' || res.message == ':HTTPOK'
            doc = REXML::Document.new(res.body)
            en_word = doc.elements['GetDicItemResult/Head/div/span'].get_text.value
            ja_word = doc.elements['GetDicItemResult/Body/div/div'].get_text.value
            if match == "STARTWITH" && text != en_word
              map[en_word] = ja_word
            elsif match == "EXACT"
              map[en_word] = ja_word
            end
          end
        end
      end
      content_type :json
      map.to_json
    end
  end
end

get "/" do
  erb :index
end

このsinatraアプリケーションをgoogle app engine上にアップするのに、以下のURLの通りに行った。
http://code.google.com/p/appengine-jruby/wiki/GettingStarted
ubuntu10.4で、ソースからコンパイルしたruby1.9.2を使用しているのだが、最初は以下のエラーが出て、全然うまくいかなかった。

$ appcfg.rb generate_app myapp
=> Generating gemfile
/usr/local/lib/ruby/gems/1.9.1/gems/appengine-tools-0.0.16/lib/appengine-tools/gem_bundler.rb:63: warning: already initialized constant RUBY_ENGINE
=> Bundling gems
ERROR:  While executing gem ... (RuntimeError)
    can't add a new key into hash during iteration

ソースからコンパイルしたjrubyでも行ったが、同じようなエラーが出て上手くいかず。ruby1.8でも同じように上手くいかず。Macでもトライしたがダメ。

結論から言うと、以下のjRubyのページから、バイナリ版をダウンロードし、それを使用したら、上手くいった。何故だろうか。
http://www.jruby.org/download

あとgoogle app engineにあげる上で、気をつけるのは以下。
myapp/config.ru

require 'appengine-apis/urlfetch'
require 'html5_server'
run Sinatra::Application

myapp/Gemfile

# Critical default settings:
disable_system_gems
disable_rubygems
bundle_path ".gems/bundler_gems"

# List gems to bundle here:
#gem 'appengine-rack', '0.0.11.pre'
gem "dm-appengine"
gem "sinatra"
gem "json"

アップロードしたら、何とか上手くいった!
ただ、ローカルで稼働させていた時は、それなりに早かったが、サーバ上だとけっこう遅い。ソースを書き直した方がいいのか、それともjrubyではなく、javaかpythonで書いた方が早くなるのかな。




次ページへ »


Ads by Sitemix