myfinderの技術や周辺的活動のblog

2009年1月30日金曜日

CentOS5.2と合うintelのマザーボード - 続報 -

昨日書き忘れました。
DQ35MPを使う場合はBIOSのバージョンに注意してください。

「BIOS Version 0704」未満のバージョンの場合、QuadCoreのCPUが利用できない問題があるようです。
intelのBIOSアップデートリリースノートにそんな内容が書いてありました。

というわけで、使うかたは最新のBIOSにアップすることを推奨します。

と、ここまで書いて、前回お薦めした根拠が覆されたのであった。。。

2009年1月29日木曜日

CentOS5.2と合うintelのマザーボード

先日intel DG45IDでNICが認識しない問題などと題してエントリを上げたのだけども、
そのあとで(特に何もしなくても)NICが動くintelのマザーボードみっけました。

Intel Desktop Board DQ35MPです。

こいつはちゃんとNICを認識するし、何よりインターフェースがシンプルでよけいなものがついてないのでいい感じです。
「CentOS5.2で自宅サーバしてみたい!」とか、あるいは「業務用に自作が必要なんです、MicroATXで」などというはてなとかpixivのようなインフラをやっている方には参考にしていただければなどと。

NICの認識はある程度自力で頑張ればどうにかなるけど、はじめから悩まないですむやつを買った方が時間を有意義に使えると思います。

では。

GenesisLightningTalksの本質はその自由性にある

タイトルはホッテントry

というわけで今月もGenesisLightningTalksに参加してきました。
このイベントは前回まで違う名前だったのだけども、3度目の参加。
資料はGenesisLightningTalksのWikiに過去のも合わせてはっつけてあります。

1回目は自宅(他宅だけど)サーバと仮想マシンで ちょっとした構成を組んでみた話。
2回目は自宅サーバを運用するときに注意すべき電源の話。
そして今回は会社を変えた話。

他の参加者様の話題も結構多種多様で、
  • すぎゃーん : 臨機応変ヒッチハイク一人旅
  • なるひこ : 変化球的技術者向けカヤックのススメ
  • あきみち : 変化するインターネットトラフィック
  • yuske : 変化について
  • hyoshiok : 変えること、変えないこと。(変わること、変わらないこと)
  • やまとも : 変速機のはなし
と、テーマが「変」が入ったタイトルって縛りがあるものの、基本的にそれを何に結びつけるかは自由。
テーマを共有しつつその先は自由、というのがGenesisLightningTalksのいいところであり、「面白い」と感じられる部分なのだと、そう考えるのである。

が、今回おいらが最も印象に残ったのは、id:hyoshiokさんの「プリフェッチ」発言でした。
先読みは大事ですね。

おわり。

今日から使える実践的Tokyo Tyrantのrpm講座

タイトルはまたもホッテントリメーカーから。

先日Tokyo Tyrantについていろいろ誤解して書いてしまったので罪滅ぼし的に、
「CentOS5.2でTokyo Tyrantのrpmを作ってインストールして運用できる状態にするまで」を書いてみる。
「rpmがないと使えない〜」というrpm厨の方もこれで安心。

今回は1サーバ1インスタンスでセットアップする想定です。
レプリケーションなどはまた別の機会に。

一応自分のとこでは動きましたが、エントリの内容は無保証です。自己責任でお願いします。

手順は大まかに言うと↓のような感じ。
  1. Tokyo CabinetとTokyo Tyrantのソースアーカイブを手に入れる
  2. rpmを作る
  3. Tokyo Tyrantが依存している別のパッケージをインストールする
  4. Tokyo Tyrantをインストールする
  5. Tokyo Tyrantをchkconfigに登録する
  6. logrotateに登録してログの肥大化を防ぐ

1.Tokyo CabinetとTokyo Tyrantのソースアーカイブを手に入れる

何はともあれTokyo Cabinetの公式サイトから
  • tokyocabinet-{version}.tar.gz
  • tokyotyrant-{version}.tar.gz
を手に入れてきます。
今回のエントリでは、Tokyo Cabinetは1.4.3、Tokyo Tyrantは1.1.11の両方とも最新版を利用しました。

2. rpmを作る

rpmを作るにはいくつか方法がありますが、今回はrpmbuildコマンドを使いますので事前にインストールしておいてください。
rpmを作るときは、できれば一般ユーザのhomeに領域を作った方がよいです。
なので、まずは一般ユーザで下記のようにrpmを作るための環境を準備します。


$ mkdir -p ~/rpm/{BUILD,SOURCES,SPECS,RPMS,SRPMS}
$ vi ~/.rpmmacros

%_topdir /home/hoge/rpm

ここまでできたら、次はrpmを作成するのに必要なSPECファイルを作ります。
おいらが作るときに使ったSPECファイルを公開しておきます、適当に参考にしてください。
まずはTokyo CabinetのSPECを書きます。


$ vi ~/rpm/SPECS/tokyocabinet.spec

Summary: A modern implementation of a DBM
Name: tokyocabinet
Version: 1.4.3
Release: 1
License: LGPLv2+
Group: Development/Libraries
URL: http://tokyocabinet.sourceforge.net/
Source: http://tokyocabinet.sourceforge.net/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: pkgconfig zlib-devel autoconf
BuildRequires: lua-devel

%description
Tokyo Cabinet is a library of routines for managing a database. It is the
successor of QDBM. Tokyo Cabinet runs very fast. For example, the time required
to store 1 million records is 1.5 seconds for a hash database and 2.2 seconds
for a B+ tree database. Moreover, the database size is very small and can be up
to 8EB. Furthermore, the scalability of Tokyo Cabinet is great.

%package devel
Summary: Headers for developing programs that will use %{name}
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
Requires: pkgconfig

%description devel
This package contains the libraries and header files needed for
developing with %{name}.

%prep
%setup -q

%build
autoconf
%configure CFLAGS="$CFLAGS" --enable-lua
make %{?_smp_mflags}

%install
rm -rf %{buildroot}
make DESTDIR=%{buildroot} install

rm -rf %{buildroot}%{_datadir}/%{name}
rm -rf %{buildroot}%{_libdir}/lib%{name}.a

#%check
#make check

%clean
rm -rf %{buildroot}

%post -p /sbin/ldconfig

%postun -p /sbin/ldconfig

%files
%defattr(-, root, root, -)
%doc ChangeLog COPYING README
%{_bindir}/tc*
%{_libdir}/libtokyocabinet.so.*
%{_mandir}/man1/tc*.gz
%{_libexecdir}/tcawmgr.cgi

%files devel
%defattr(-, root, root, -)
%{_includedir}/tc*.h
%{_libdir}/*.so
%{_libdir}/pkgconfig/%{name}.pc
%{_mandir}/man3/t*.gz
%doc doc/*

%changelog
* Thu Jan 29 2009 myfinder
- New Build

次にTokyo TyrantのSPECを作成します。


$ vi ~/rpm/SPECS/tokyotyrant.spec

Summary: Network Interface for TokyoCabinet
Name: tokyotyrant
Version: 1.1.11
Release: 1
License: LGPLv2+
Group: Development/Libraries
URL: http://tokyocabinet.sourceforge.net/tyrantdoc/
Source: http://tokyocabinet.sourceforge.net/tyrantpkg/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: pkgconfig zlib-devel autoconf
BuildRequires: lua-devel

%description
Tokyo Tyrant is a package of network interface to the DBM called Tokyo Cabinet.
Though the DBM has high performance, you might bother in case that multiple processes share the same database, or remote processes access the database.
Thus, Tokyo Tyrant is provided for concurrent and remote connections to Tokyo Cabinet.
It is composed of the server process managing a database and its access library for client applications.
The server can embed Lua, a lightweight script language so that you can define arbitrary operations of the database.

%package devel
Summary: Headers for developing programs that will use %{name}
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
Requires: pkgconfig

%description devel
This package contains the libraries and header files needed for
developing with %{name}.

%prep
%setup -q

%build
autoconf
%configure CFLAGS="$CFLAGS" --enable-lua
make %{?_smp_mflags}

%install
rm -rf %{buildroot}
make DESTDIR=%{buildroot} install

rm -rf %{buildroot}%{_datadir}/%{name}
rm -rf %{buildroot}%{_libdir}/lib%{name}.a

#%check
#make check

%clean
rm -rf %{buildroot}

%post -p /sbin/ldconfig

%postun -p /sbin/ldconfig

%files
%defattr(-, root, root, -)
%doc ChangeLog COPYING README
%{_bindir}/t*
%{_sbindir}/t*
%{_libdir}/libtokyotyrant.so.*
%{_mandir}/man1/t*.gz
%{_mandir}/man8/t*.gz

%files devel
%defattr(-, root, root, -)
%{_includedir}/*.h
%{_libdir}/*.so
%{_libdir}/pkgconfig/%{name}.pc
%{_mandir}/man3/t*.gz
%doc doc/*

%changelog
* Thu Jan 29 2009 myfinder
- New Build

ここまでできたら、入手したソースアーカイブを、~/rpm/SOURCES/に放り込みます。
放り込んだらrpmbuildコマンドでrpmを作りましょう。


$ rpmbuild -ba ~/rpm/SPECS/tokyocabinet.spec
$ rpmbuild -ba ~/rpm/SPECS/tokyotyrant.spec

RPMファイルは、" ~/rpm/RPMS/{architecture}/"以下に作成されます。

3. Tokyo Cabinet&Tokyo Tyrantが依存しているパッケージをインストールする

luaサポートをonにしたいので、lua-develをyumかなにかで導入しておきましょう。


$ sudo yum install lua-devel


4. Tokyo Tyrantをインストールする

~/rpm/RPMS/{architecture}/以下に出来上がっているrpmをインストールします。


$ sudo rpm -ivh ~/rpm/RPMS/{architecture}/tokyo*

インストールがウマいこといけば↓のファイルがインストールされます。
(manの表示はカットしました)


$ rpm -ql tokyotyrant
/usr/bin/tcrmgr
/usr/bin/tcrmttest
/usr/bin/tcrtest
/usr/bin/ttserver
/usr/bin/ttulmgr
/usr/bin/ttultest
/usr/lib/libtokyotyrant.so.2
/usr/lib/libtokyotyrant.so.2.3.0
/usr/sbin/ttservctl
/usr/share/doc/tokyotyrant-1.1.11
/usr/share/doc/tokyotyrant-1.1.11/COPYING
/usr/share/doc/tokyotyrant-1.1.11/ChangeLog
/usr/share/doc/tokyotyrant-1.1.11/README
$ rpm -ql tokyocabinet
/usr/bin/tcamgr
/usr/bin/tcatest
/usr/bin/tcbmgr
/usr/bin/tcbmttest
/usr/bin/tcbtest
/usr/bin/tcfmgr
/usr/bin/tcfmttest
/usr/bin/tcftest
/usr/bin/tchmgr
/usr/bin/tchmttest
/usr/bin/tchtest
/usr/bin/tctmgr
/usr/bin/tctmttest
/usr/bin/tcttest
/usr/bin/tcucodec
/usr/bin/tcumttest
/usr/bin/tcutest
/usr/lib/libtokyocabinet.so.7
/usr/lib/libtokyocabinet.so.7.6.0
/usr/libexec/tcawmgr.cgi
/usr/share/doc/tokyocabinet-1.4.3
/usr/share/doc/tokyocabinet-1.4.3/COPYING
/usr/share/doc/tokyocabinet-1.4.3/ChangeLog
/usr/share/doc/tokyocabinet-1.4.3/README

ここまでくればほぼ大丈夫ですが、動作確認はしときましょう。


# ttserver
2009-01-27T14:48:56+09:00 --------- logging started [23008] --------
2009-01-27T14:48:56+09:00 server configuration: host=(any) port=1978
2009-01-27T14:48:56+09:00 database configuration: name=*
2009-01-27T14:48:56+09:00 service started: 23008
2009-01-27T14:48:56+09:00 timer thread started
2009-01-27T14:48:56+09:00 worker thread 1 started
2009-01-27T14:48:56+09:00 worker thread 2 started
2009-01-27T14:48:56+09:00 worker thread 3 started
2009-01-27T14:48:56+09:00 worker thread 4 started
2009-01-27T14:48:56+09:00 worker thread 5 started
2009-01-27T14:48:56+09:00 worker thread 6 started
2009-01-27T14:48:56+09:00 worker thread 7 started
2009-01-27T14:48:56+09:00 worker thread 8 started
2009-01-27T14:48:56+09:00 listening started

こうなればOK、とりあえず「Ctrl+C」で切ってしまいましょう。

5. Tokyo Tyrantをchkconfigに登録する

Tokyo Tyrantをchkconfigに登録するのは簡単で、/usr/sbin/ttservctlに↓の数行追加するだけ。


# vi /usr/sbin/ttservctl

# chkconfig: 345 65 55
# description: Startup script for the server of Tokyo Tyrant
# processname: tokyotyrant

追記できたら/etc/init.dにリンクを作ってchkconfigに登録します。


# ln -s /usr/sbin/ttservctl /etc/init.d/
# chkconfig --add ttservctl
# chkconfig --list ttservctl
ttservctl 0:off 1:off 2:off 3:on 4:on 5:on 6:off

起動して確認しましょう


# /etc/init.d/ttservctl start
Starting the server of Tokyo Tyrant
Done

さらにtelnetでつないで確認します


# telnet localhost 1978
Trying 127.0.0.1...
Connected to hostname.localdomain (127.0.0.1).
Escape character is '^]'.
stats
STAT pid 23121
STAT uptime 18
STAT time 1233035968
STAT version 1.1.11
STAT rusage_user 0.000000
STAT rusage_system 0.018997
STAT curr_items 0
STAT bytes 4198720
END
quit

ここまで確認できれば、もうインストールは完了です。
が、運用を楽にするためにもうひと手間掛けましょう。

6. logrotateに登録する

/var/ttserver/logにTokyo Tyrantのログが書き出されるのですが、これを放置しておくと勝手に肥大化していって大変です。
こういうのはログをローテーションする仕組みに任せてしまうのが楽です。


# vi /etc/logrotate.d/tokyotyrant

/var/ttserver/log {
compress
missingok
notifempty
sharedscripts
postrotate
/sbin/service ttservctl hup > /dev/null 2>/dev/null || true
endscript
}


Tokyo Tyrantの起動停止スクリプトがHUPをフォローしてくれているので、これだけでOKというのが何とも楽でいい感じです。

ここまでやっておけば、永続化機能のついた、OSごと再起動が掛かっても勝手に復活するmemcachedサーバ的な使い方が出来るようになります。

今日はこんなもんで。

2009年1月28日水曜日

人生に役立つかもしれないTokyo Tyrantについての知識 続報

昨夜上げたエントリで、TTはFlagを無視する?という疑問とその状況について書いたのですが。
今朝改めてTTのドキュメントをさらったところ、下記のように書いてありました。

However, "flags", "exptime", and "cas unique" parameters are ignored.

つまり、flagsは無視されるようです。
ということなので、memcachedプロトコルを実直に実装したクライアントライブラリだと、昨日エントリしたような状況が発生する可能性があるという話でした。

ドキュメント仕様は真っ先に取りまとめて比較するようにしないと、思わぬところで足元をすくわれるので注意したいところです。

昨日のおいら、おつ。
TTの開発者様、失礼いたしました。

おわり。

2009年1月27日火曜日

人生に役立つかもしれないTokyo Tyrantについての知識

タイトルはホッテントリメーカーから頂戴しました。

お仕事でmemcachedとかその周辺プロダクトを利用することとなり、memcached、Tokyo Tyrant、Flareのパフォーマンスを測ってみたときに発覚したことを書いておきます。
(前提条件:memcached client for Javaからmemcachedとかその互換プロダクトを利用する場合)

まずはパフォーマンスの手っ取り早い指標として処理速度があげられるので、上記3プロダクトをセットアップして、下記のようなテストプログラムをそそくさとこさえました。


public static void main(String[] args) {

// memcacheのインスタンス取得
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(new String[] {"hostname:port"});
pool.initialize();
MemCachedClient memcache = new MemCachedClient();

// 計測用
long start = 0;
long finish = 0;

// setのパフォーマンステスト
System.out.println("setのテスト開始...");
start = System.currentTimeMillis();
// setのテスト
for (Iterator<Map.Entry<String, String>> it = TEST_DATA_HASH.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
memcache.set(entry.getKey(), entry.getValue());
}
finish = System.currentTimeMillis();
System.out.println(TEST_DATA_HASH.size() + "件のsetにかかった時間 : " + (finish - start) + "ms");

// getのパフォーマンステスト
System.out.println("getのテスト開始...");
start = System.currentTimeMillis();
int count = 0;
for (Iterator<Map.Entry<String, String>> it = TEST_DATA_HASH.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
String value = "";
value = (String)memcache.get(entry.getKey());
// get1万件ごとにprintして確認
if ((count % 10000) == 0) {
System.out.println(value);
}
++count;
}
finish = System.currentTimeMillis();
System.out.println(TEST_DATA_HASH.size() + "件のgetにかかった時間 : " + (finish - start) + "ms");
}

データはおよそ10万件の固定長(32byte)のキーと、100-300byte程度の英数字記号のみの文字列。
テストに使ったマシンはP4 2.8GHzにRAM 3GBです。

プロダクトsetにかかった時間(ms)getにかかった時間(ms)
memcached3412658182
Tokyo Tyrant3617063023
Flare4267462938

値自体はおおよそ想定された内容だった。(TTのsetがこれほど速いとは思ってなかったけど)
のだが、Tokyo Tyrantのgetパフォーマンスを計測している時に異変が起こりました。
さっきsetした文字列データをgetするのだから、文字列がprintされるはずなのに、「null」と出力されてしまっているのです。
(つまりnullが返ってきている)

これはどうしたものかと思い、直接telnetしてmemcacheと対話してみました。

・memcached
user@host:$ telnet host 11211
Trying host...
Connected to host.
Escape character is '^]'.
get keykeykeykeykeykeykeykeykeykeyke
VALUE keykeykeykeykeykeykeykeykeykeyke 32 64
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
END
quit
Connection closed by foreign host.

・Tokyo Tyrant
user@host:$ telnet host 1978
Trying host...
Connected to host.
Escape character is '^]'.
get keykeykeykeykeykeykeykeykeykeyke
VALUE keykeykeykeykeykeykeykeykeykeyke 0 64
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
END
quit
Connection closed by foreign host.

・Flare
user@host:$ telnet host 12121
Trying host...
Connected to host.
Escape character is '^]'.
get keykeykeykeykeykeykeykeykeykeyke
VALUE keykeykeykeykeykeykeykeykeykeyke 32 64
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
END
Connection closed by foreign host.

結果、Tokyo Tyrantだけflagが0で返ってくる。
telnetで確認してみるとデータは返ってくるのに、nullになってしまうのはなぜかとmemcached client for javaのflag処理がどうなっているかを追っていき、そのflagの処理を見てみると

public static Object decode( byte[] b, int flag ) throws Exception {
if ( b.length < 1 )
return null;
if ( ( flag & MemCachedClient.MARKER_BYTE ) == MemCachedClient.MARKER_BYTE )
return decodeByte( b );
if ( ( flag & MemCachedClient.MARKER_BOOLEAN ) == MemCachedClient.MARKER_BOOLEAN )
return decodeBoolean( b );
if ( ( flag & MemCachedClient.MARKER_INTEGER ) == MemCachedClient.MARKER_INTEGER )
return decodeInteger( b );
if ( ( flag & MemCachedClient.MARKER_LONG ) == MemCachedClient.MARKER_LONG )
return decodeLong( b );
if ( ( flag & MemCachedClient.MARKER_CHARACTER ) == MemCachedClient.MARKER_CHARACTER )
return decodeCharacter( b );
if ( ( flag & MemCachedClient.MARKER_STRING ) == MemCachedClient.MARKER_STRING )
return decodeString( b );
if ( ( flag & MemCachedClient.MARKER_STRINGBUFFER ) == MemCachedClient.MARKER_STRINGBUFFER )
return decodeStringBuffer( b );
if ( ( flag & MemCachedClient.MARKER_FLOAT ) == MemCachedClient.MARKER_FLOAT )
return decodeFloat( b );
if ( ( flag & MemCachedClient.MARKER_SHORT ) == MemCachedClient.MARKER_SHORT )
return decodeShort( b );
if ( ( flag & MemCachedClient.MARKER_DOUBLE ) == MemCachedClient.MARKER_DOUBLE )
return decodeDouble( b );
if ( ( flag & MemCachedClient.MARKER_DATE ) == MemCachedClient.MARKER_DATE )
return decodeDate( b );
if ( ( flag & MemCachedClient.MARKER_STRINGBUILDER ) == MemCachedClient.MARKER_STRINGBUILDER )
return decodeStringBuilder( b );
if ( ( flag & MemCachedClient.MARKER_BYTEARR ) == MemCachedClient.MARKER_BYTEARR )
return decodeByteArr( b );
return null;
}

となっていました。
この処理では、受け取ったデータをどのクラスにキャストするかをflagsで判断しているようなのですが、flagsに0が返ってきてしまうTokyo Tyrantではどのflagにも該当しません。
よってreturn nullされて、データはgetできているにも関わらずnullとなってしまうという問題が起こっていたことが見て取れます。

これって大丈夫なのかな〜。
全部文字列(Stringなど)として受け取るという前提でTTは実装されているのかも。
(myfinderの認識が間違っていたら申し訳ないのですが)

型に緩いLLならそもそもキャストする処理が不要なのでそもそもクライアントライブラリがflagを見ていないのかもしれない。
(mixiはPerlから利用しているみたいだし)

というかクライアントライブラリも、あり得ないflagが返ってきたなら例外をスローしたほうがいいんじゃないかというツッコミを入れたいところ。

少なくともmemcached client for JavaからTokyo Tyrantを利用するときは、そういうことがあるということは覚えておかないと、setできるけどgetするとnullが返ってくるという、ブラックホール状態になってしまうので注意です。

結論としては、Tokyo Tyrantをmemcached client for Javaから使う場合、改修をする必要があり、それがいやならmemcachedクライアントを自作するなどの対策が必要ですよというオチでした。
パフォーマンス計測結果とその計測プログラムは参考程度にお使いください。

では。

2009年1月26日月曜日

プログラむ

ちょっと行列をやる必要があったので、簡単に書いたもの。


public class Matrix {
private String[][] matrix;
private int row;
private int column;

public Matrix(String[][] matrix) {
// 行列本体
this.matrix = matrix;
// 行数取得
this.row = this.matrix.length;
if (row == 0) {
this.column = 0;
}
else {
this.column = this.matrix[0].length;
}
}

public String[][] transport (){
String[][] transportedArray = new String[column][row];
for (int i = 0; i < column; ++i) {
for (int j = 0; j < row; ++j) {
transportedArray[i][j] = matrix[j][i];
}
}
return transportedArray;
}
}


だんだんメソッドとかフィールドが増えていく予感。

2009年1月21日水曜日

プログラミングの基礎体力その1「転置配列」

自分の能力レーダーチャートを作ってみるとすると、圧倒的に「プログラむ」力が不足しているのは前々から思っていて、どうにかしないといかんと考えていた。
なので、しばらくの間このシリーズをやってみるです。

今回実装したのは転置配列的な処理。
入力CSVを反転させるものです。

以下コード


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CSVReverse {

private static final String DELIMITER = ",";

/**
* main
* @param args
* @throws FileNotFoundException
* @throws IOException
*/
public static void main(String[] args) throws FileNotFoundException, IOException, IOException {

FileReader fileReader = new FileReader("sampleData/examination.csv");
BufferedReader bufferedReader = new BufferedReader(fileReader);
List splittedList = new ArrayList();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
splittedList.add(line.split(DELIMITER));

}

String[][] splittedArray = splittedList.toArray(new String[splittedList.size()][]);
int row = splittedArray.length;
int column = 0;
if (row != 0) {
column = splittedArray[0].length;
}

String[][] transportedArray = new String[column][row];
// 行と列を反転させる
for (int i = 0; i < column; ++i) {
for (int j = 0; j < row; ++j) {
/**
* こうすれば
* 元行列[0][0] 変換行列[0][0]
* 元行列[0][1] 変換行列[1][0]
* 元行列[0][2] 変換行列[2][0]
* 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
* という感じに置き換えができる
*/
transportedArray[i][j] = splittedArray[j][i];
}
}
StringBuilder transportedString = new StringBuilder();
for (String[] transportedLineArray : transportedArray) {
for (int i = 0; i < transportedLineArray.length; ++i) {
transportedString.append(transportedLineArray[i]);
if (i != transportedLineArray.length - 1) {
transportedString.append(DELIMITER);
}
}
transportedString.append(System.getProperty("line.separator"));
}

FileWriter fileWriter = new FileWriter("resultData/transported.csv");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(transportedString.toString());
bufferedWriter.close();
}
}


たったこれだけなのに時間掛かり過ぎ。
もっと書かないといかんです。

2009年1月11日日曜日

NetBeans6.5ビルトインのTomcat6のコンソール出力が文字化けする件

先日NetBeansのJavaコンソールが文字化けする件を書いた続報。
Servletアプリケーションを作り始めて、標準出力が化けることに気づいたので備忘録的に書いておきます。

NetBeans6.5からTomcatを起動する場合、Javaの起動引数設定を下の画像のようにしておくと、化けません。