近況
なんだかんだで, 前回のエントリから1年経っていまいました(汗)
最近は, はてなダイアリに書いています.
なんだかんだで, 前回のエントリから1年経っていまいました(汗)
最近は, はてなダイアリに書いています.
GW 中にやったことをちょっとまとめてみる...
インフラまわりは, ほとんど深夜やっていたので, 寝るのは午前中って感じでした...
でも, かなりすっきり.
毎年のことなのですが, うちの会社の「確定深刻」は GW 勝負なのです(汗)
今年は, e-Tax を使ってみましたが, イマイチ便利になってない...
税務署へ持って行く手間はなくなりましたが, 事業税などの申告は別にやらなきゃいけないし, 電子証明書の申請をしに法務局へ行かなきゃいけない.
数字の計算くらい, 明細書から自動計算してくれれば楽なのに(苦笑)
FreeBSD 4.11-RELEASE が, まだ4台稼動していたので, すべて 6.3-RELEASE にアップグレード.
Celeron 700MHz という骨董品ですが, これでまた, 暫くは心おきなく使えますw
手順は, 下記とほとんど同じ
FreeBSD4 から FreeBSD6 へのアップグレード
上記の FreeBSD4.11-RELEASE で稼動していたうちの3台を, jail(8) を使って1台に統合しました.
減らしたやつは, 予備機として頑張ってもらいます.
sysutils/ezjail を使って構築も楽ちん.
ipfilter は, 今後メンテされなくなるようなので, 6.3-RELEASE へアップグレードしたついでに, pf へ乗り替え.
構文もすっきりして, メンテもしやすくなりました.
特に, ルータとして使っているやつは, 細かい設定ができてステキ.
set block-policy drop とか良い感じです.
下記を参考にしました
FreeBSDでPacketFilter(pf)を使う
4.11-RELEASE が現在までも稼動していたのもそうですが, 過去に書いたバックアップスクリプトとかを, メンテしやすいようにいろいろ更新. サーバーで USBキーボードを使えるようにしたりだとか...
あ, DHCP サーバーも jail(8) で動くようにして, WIDE-DHCP を net/isc-dhcpd-server にしました.

山本さん, 大変永らくお待たせ致しました...(汗)
また, 拙作のアイコンをご採用頂き, ありがとうございました!
EC-CUBE をほとんど触れなかったのがざんねん...
もうちょっと精進します...
今まで, Windows 環境では Meadow を使っていましたが, NTEmacs もちょっと気になって NTEmacsJp project の NTEmacs を入れてみました.
そしたら, アイコンが Emacs23 と同タイプになっているではありませんか!!
感謝感激!! 廣松さん, ありがとうございます!
使い心地は, 良い感じ.
気のせいかもしれませんが, Meadow に比べると, ちょっと速くなったような感じがします.
でも, Meadow みたいに NetInstall で簡単に設定することができないので, 玄人向けですね.
しかし, Windows 環境でも, Emacs23 のアイコンが使えてシアワセです.
かなり前に書いた記事を, ちゃんとまとめてみました.
BeanUtils の使い方サンプルです.
JUnit4 のテストケースとして書いてみました.
/*
* $Id$
*/
package net.nanasess.examples;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Before;
import org.junit.Test;
/**
* BeanUtils の使い方.
*
* 基本的に, データ型を String に変換して返します.
* 変換したくない場合は, {@link PropertyUtils} を使います.
*
* @author Kentaro Ohkouchi
* @version $Revision$ $Date$
*/
public class BeanUtilsTest {
private FooBar fooBar;
@Before
public void before() {
fooBar = new FooBar();
}
/**
* {@link BeanUtils#cloneBean(java.lang.Object)} の使い方.
*
* Cloneable を implements してなくても Bean の複製ができます.
*/
@Test
public final void testCloneBean() throws Exception {
Bar bar = new Bar("bar");
String excepted = "bar";
// bar を複製する
Bar actual = (Bar) BeanUtils.cloneBean(bar);
assertEquals(excepted, actual.getExample());
}
/**
* {@link BeanUtils#copyProperties(java.lang.Object, java.lang.Object)} の使い方
*
* 同じプロパティ名のデータを orig から dest へコピーします.
* この場合, example というプロパティが双方に存在するので, example のデータがコピーされます.
*/
@Test
public final void testCopyProperties() throws Exception {
Bar orig = new Bar();
ExampleClass dest = new ExampleClass();
// 同じプロパティ名のデータを orig から dest へコピーする.
BeanUtils.copyProperties(dest, orig);
// orig が Map の場合は, プロパティ名と Map の key が一致した場合コピーされる.
Map map = new HashMap();
map.put("foo", "foo");
BeanUtils.copyProperties(dest, map);
// example の内容がコピーされる
assertEquals(orig.getExample(), dest.getExample());
// Map の内容もコピーされる
assertEquals(map.get("foo"), dest.getFoo());
// baz は null のまま
assertNull(dest.getBaz());
}
/**
* {@link BeanUtils#copyProperty(java.lang.Object, java.lang.String, java.lang.Object)} の使い方.
*
* 指定したプロパティのデータをコピーします.
* ネストしたプロパティもコピーできます.
*/
@Test
public final void testCopyProperty() throws Exception {
Bar bar = new Bar();
ExampleClass bean = new ExampleClass();
// 指定したプロパティのデータを bean にコピーします.
BeanUtils.copyProperty(bean, "foo", "foo");
// ネストした Bean もコピーできます.
BeanUtils.copyProperty(bean, "bar", bar);
assertEquals("foo", bean.getFoo());
assertEquals("example", bean.getBar().getExample());
}
/**
* {@link BeanUtils#describe(java.lang.Object)} の使い方.
*
* bean のプロパティ名を key, プロパティのデータを value とした Map を返します.
* プロパティのデータ型に関わらず, value は String になります...
*/
@Test
public final void testDescribe() throws Exception {
// value に格納されるデータを String にキャストして Map で返します.
Map map = BeanUtils.describe(fooBar);
assertEquals("foo", map.get("foo"));
}
/**
* {@link BeanUtils#getArrayProperty(java.lang.Object, java.lang.String)} の使い方.
*
* プロパティ名を指定して, プロパティの値を String の配列で返します.
* プロパティのデータ型が配列の場合は, String の配列に変換して返します.
* コレクションの場合も, String の配列に変換して返します.
* それ以外のデータ型の場合は, {@link Object#toString()} の値を String の配列に格納して返します.
*/
@Test
public final void testGetArrayProperty() throws Exception {
// プロパティ名を指定して, String の配列を返します.
String[] strings = BeanUtils.getArrayProperty(fooBar, "strings");
assertArrayEquals(fooBar.getStrings(), strings);
// プロパティが配列では無い場合も String の配列が返ってきます.
String[] foo = BeanUtils.getArrayProperty(fooBar, "foo");
assertArrayEquals(new String[]{"foo"}, foo);
}
/**
* {@link BeanUtils#getIndexedProperty(java.lang.Object, java.lang.String)} の使い方.
*
* プロパティ名[インデックス番号] のように, インデックスを保持するプロパティから, インデックス番号を指定して
* 値を String で返します.
* インデックスを保持しないプロパティは, {@link IllegalArgumentException} になります.
*/
@Test(expected=IllegalArgumentException.class)
public final void testGetIndexedPropertyObjectString() throws Exception {
// プロパティ名とインデックス番号を指定して String の値を返します.
String actual = BeanUtils.getIndexedProperty(fooBar, "strings[2]");
assertEquals("ghi", actual);
// インデックスを保持しないプロパティは IllegalArgumentException になります.
String foo = BeanUtils.getIndexedProperty(fooBar, "foo[0]");
}
/**
* {@link BeanUtils#getIndexedProperty(java.lang.Object, java.lang.String, int)} の使い方.
*
* {@link BeanUtils#getIndexedProperty(java.lang.Object, java.lang.String)} に
* 似ていますが, インデックス番号を int で指定するところが異なります.
*/
@Test
public final void testGetIndexedPropertyObjectStringInt() throws Exception {
// プロパティ名とインデックス番号を指定して, String の値を取得します.
String actual = BeanUtils.getIndexedProperty(fooBar, "strings", 2);
assertEquals("ghi", actual);
}
/**
* {@link BeanUtils#getMappedProperty(java.lang.Object, java.lang.String)} の使い方.
*
* プロパティが Map の場合, プロパティ名(key) のように指定して, 値を String で返します.
* プロパティが Map 以外の場合は, null を返します.
*/
@Test
public final void testGetMappedPropertyObjectString() throws Exception {
// プロパティ名と key を指定して, String の値を返します.
String actual = BeanUtils.getMappedProperty(fooBar, "map(abc)");
assertEquals("abc of value", actual);
// プロパティが Map 以外の場合は, null を返します.
assertNull(BeanUtils.getMappedProperty(fooBar, "foo(key)"));
}
/**
* {@link BeanUtils#getMappedProperty(java.lang.Object, java.lang.String, java.lang.String)} の使い方.
*
* {@link BeanUtils#getMappedProperty(java.lang.Object, java.lang.String)} に
* 似ていますが, key を第3引数で指定するところが異なります.
*/
@Test
public final void testGetMappedPropertyObjectStringString() throws Exception {
// プロパティ名と key を指定して, String の値を返します.
String actual = BeanUtils.getMappedProperty(fooBar, "map", "abc");
assertEquals("abc of value", actual);
}
/**
* {@link BeanUtils#getNestedProperty(java.lang.Object, java.lang.String)} の使い方.
*
* ネストした Bean のプロパティをドットシンタックスで取得できます.
* 値は String で返します.
*/
@Test
public final void testGetNestedProperty() throws Exception {
// ネストしたプロパティを取得します.
String actual = BeanUtils.getNestedProperty(fooBar, "bar.example");
assertEquals("example", actual);
}
/**
* {@link BeanUtils#getProperty(java.lang.Object, java.lang.String)} の使い方.
*
* 便利屋さんです.
* プロパティのデータ型に合わせた方法で, プロパティ名やインデックスを指定することで, プロパティの値を
* String で取得できます.
*/
@Test
public final void testGetProperty() throws Exception {
// プロパティ名を指定して String の値を返します.
String foo = BeanUtils.getProperty(fooBar, "foo");
assertEquals("foo", foo);
// プロパティ名とインデックス番号を指定して String の値を返します.
String strings = BeanUtils.getProperty(fooBar, "strings[2]");
assertEquals("ghi", strings);
// プロパティ名と key を指定して, String の値を返します.
String map = BeanUtils.getProperty(fooBar, "map(abc)");
assertEquals("abc of value", map);
// ネストしたプロパティを取得します.
String actual = BeanUtils.getProperty(fooBar, "bar.example");
assertEquals("example", actual);
}
/**
* {@link BeanUtils#getSimpleProperty(java.lang.Object, java.lang.String)} の使い方.
*
* プロパティ名を指定して, String の値を返します.
* {@link BeanUtils#getProperty(java.lang.Object, java.lang.String)} とは挙動が
* 異なるため, 単純な Bean の値を取得するのに適しています.
*/
@Test(expected=IllegalArgumentException.class)
public final void testGetSimpleProperty() throws Exception {
// プロパティ名を指定して String の値を返します.
String foo = BeanUtils.getSimpleProperty(fooBar, "foo");
assertEquals("foo", foo);
// プロパティが配列の場合は先頭の値を返します.
String strings = BeanUtils.getSimpleProperty(fooBar, "strings");
assertEquals("abc", strings);
// プロパティが Map の場合はMap#toString() の値を返します.
String map = BeanUtils.getSimpleProperty(fooBar, "map");
assertEquals("{abc=abc of value, ghi=ghi of value, def=def of value}", map);
// ネストしたプロパティは取得できません...
try {
BeanUtils.getSimpleProperty(fooBar, "bar.example");
} catch (IllegalArgumentException e) {
throw e;
}
}
/**
* {@link BeanUtils#populate(java.lang.Object, java.util.Map)} の使い方.
*
* Map に格納した値を key に対応する Bean のプロパティに設定します.
* 値は, String にキャストして設定します.
*/
@Test
public final void testPopulate() throws Exception {
Map map = new HashMap();
map.put("foo", "foo of value");
map.put("bar.example", new Integer(1000));
// Map の key に対応するプロパティに値を設定します.
BeanUtils.populate(fooBar, map);
assertEquals("foo of value", fooBar.getFoo());
// Integer などの値も String にキャストされます.
assertEquals("1000", fooBar.getBar().getExample());
}
/**
* {@link BeanUtils#setProperty(java.lang.Object, java.lang.String, java.lang.Object)} の使い方.
*
* {@link BeanUtils#getProperty(java.lang.Object, java.lang.String)} と同様の方法で,
* プロパティ名を指定することで, 任意のオブジェクトを String にキャストして Bean に設定します.
*/
@Test
public final void testSetProperty() throws Exception {
// プロパティ名を指定して String の値を設定します.
BeanUtils.setProperty(fooBar, "foo", "foo of value");
assertEquals("foo of value", fooBar.getFoo());
// プロパティ名とインデックス番号を指定して String の値を設定します.
BeanUtils.setProperty(fooBar, "strings[2]", "strings of two");
String[] strings = fooBar.getStrings();
assertEquals("strings of two", strings[2]);
// プロパティ名と key を指定して, String の値を設定します.
BeanUtils.setProperty(fooBar, "map(abc)", new Integer(1000));
assertEquals("1000", fooBar.getMap().get("abc"));
// ネストしたプロパティを設定します.
BeanUtils.setProperty(fooBar, "bar.example", "bar of example");
assertEquals("bar of example", fooBar.getBar().getExample());
}
}
Bean は下記のものを使っています.
/*
* $Id$
*/
package net.nanasess.examples;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* FooBar クラス.
*
* 内部で Bar クラスをネストしている.
*
* @author Kentaro Ohkouchi
* @version $Revision$ $Date$
*/
public class FooBar {
private String foo;
private Bar bar;
private String[] strings;
private List bars;
private Map map;
public FooBar() {
this.foo = "foo";
bar = new Bar();
strings = new String[]{"abc", "def", "ghi"};
bars = new ArrayList();
map = new HashMap();
for (String string : strings) {
bars.add(new Bar(string));
map.put(string, string + " of value");
}
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
public String[] getStrings() {
return strings;
}
public void setStrings(String[] strings) {
this.strings = strings;
}
public List getBars() {
return bars;
}
public void setBars(List bars) {
this.bars = bars;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
}
/*
* $Id$
*/
package net.nanasess.examples;
import java.sql.Timestamp;
/**
* Bar クラス.
*
* @author Kentaro Ohkouchi
* @version $Revision$ $Date$
*/
public class Bar {
private String example;
private Timestamp created;
public Bar() {
this.example = "example";
this.created = new Timestamp(System.currentTimeMillis());
}
public Bar(String example) {
this.example = example;
this.created = new Timestamp(System.currentTimeMillis());
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
public Timestamp getCreated() {
return created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
}
/*
* $Id$
*/
package net.nanasess.examples;
import java.sql.Timestamp;
/**
* ExampleClass クラス.
*
* @author Kentaro Ohkouchi
* @version $Revision$ $Date$
*/
public class ExampleClass {
private String foo;
private String baz;
private String example;
private Bar bar;
private Timestamp created;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public String getBaz() {
return baz;
}
public void setBaz(String baz) {
this.baz = baz;
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
public Timestamp getCreated() {
return created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
}
以前の記事にも書いたのですが, BeanUtils は, 基本的に値を String にキャストします.
PropertyUtils は, 型変換せずに扱います.
それ以外の振舞いは, 基本的に同じです.
これらの API を使いこなすと非常に強力ですが, 最近はフレームワークがサポートしている場合が多いようです.
(Seasar の S2BeanUtils など)
今回ひさびさに,
BeanUtils の使い方 の続きを読む
ずっと食わず嫌いだった JUnit4 を使ってみたので, コードを晒しておきます...
/*
* $Id$
*/
package net.nanasess.examples;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* HelloWorld のテスト.
*
* @author Kentaro Ohkouchi
* @version $Revision$ $Date$
*/
public class HelloWorldTest {
private static String expected;
private String actual;
private static int counter;
/**
* すべてのテスト前に実行するメソッド.
*
* static にして {@link @beforeClass} アノテーションをつける.
*/
@BeforeClass
public static void beforeClass() {
System.out.println("HelloWorld テストを始めます.");
counter = 0;
System.out.println("カウンターを初期化しました.");
}
/**
* すべてのテストを終了した後に実行するメソッド.
*
* static にして {@link @AfterClass} アノテーションをつける.
*/
@AfterClass
public static void afterClass() {
System.out.println(counter + " 個のテストを実行しました.");
System.out.println("HelloWorld テストを終了します.");
}
/**
* 各テストをする前に実行するメソッド.
*
* {@link @Before} アノテーションをつける.
*/
@Before
public void before(){
expected = "HelloWorld";
System.out.println("expected を初期化しました.");
}
/**
* 各テストの後に実行するメソッド.
*
* {@link @After} アノテーションをつける.
*/
@After
public void after() {
counter++;
System.out.println(String.valueOf(counter) + " 番目のテストを実行しました.");
}
/**
* HelloWorld のテスト.
*/
@Test
public void helloWorld() {
actual = "HelloWorld";
assertEquals(expected, actual);
}
/**
* ちゃんと ClassNotFoundException になるかどうかのテスト.
*
* @throws Exception エラーが発生した場合.
*/
@Test(expected = ClassNotFoundException.class)
public void classForNameFailure() throws Exception {
Class.forName("org.postgresql.Driver");
}
/**
* スタブなので, スキップするテスト.
*
* {@link @Ignore} アノテーションをつけると, そのメソッドはテストしない.
*/
@Ignore("スタブなのでテストしません...")
@Test
public void testStub() {
assertEquals("test", "stub");
}
/**
* 配列を比較するテスト.
*
* {@link org.junit.Assert#assertArrayEquals(String[], String[])} を使ってます.
* 配列や, List のテストも楽になったものです(しみじみ)
*/
@Test
public void arrays() {
String[] expecteds = { "1", "2", "3" };
List actuals = new ArrayList();
actuals.add("1");
actuals.add("2");
actuals.add("3");
assertArrayEquals(expecteds, actuals.toArray(new String[actuals.size()]));
}
}
個人的には, 配列や例外のテストが解りやすく楽になったのが良い感じ.
JUnit4 の関連ライブラリも充実してきたので, そろそろ乗り替え時かな...
ついでに, Eclipse 3.4M6a を Celeron 600MHz, メモリ 384MB という非力なノートPCで使ってみましたが, 思ったよりサクサクで良い感じでした☆
MT4 で サイトマップ(sitemap.xml)を作成 を参考に, sitemap.xml も作ってみました.
FastCGI といい, こうやって細かいチューニングができるのは, 自前サーバーの強みですね...
最近, スパムコメントやスパムトラックバックで, サーバーの負荷が酷な状態になっていたため, 負荷低減のために MovableType を FastCGI で動作するようにしてみました.
参考 http://wiki.movabletype.org/Hosting_MT_under_FastCGI_(Japanese)
# portinstall www/p5-FastCGI
# portinstall www/mod_fastcgi
portupgrade を使わない場合は, /usr/ports/www/p5-FastCGI, /usr/ports/www/mod_fastcgi で make install で OK
LoadModule fastcgi_module libexec/apache2/mod_fastcgi.so
<IfModule fastcgi_module>
FastCgiIpcDir /var/tmp/fcgi_ipc/
AddHandler fastcgi-script fcgi
FastCGIConfig -autoUpdate -idle-timeout 120 -killInterval 3600 -maxClassProcesses 6 -maxProcesses 15
</IfModule>
# apachectl restart
$ cp mt.cgi mt.fcgi $ cp mt-tb.cgi mt-tb.cgi $ cp mt-comments.cgi mt-comments.fcgi $ cp mt-search.cgi mt-search.fcgi $ cp mt-view.cgi mt-view.fcgi
AdminScript mt.fcgi CommentScript mt-comments.fcgi TrackbackScript mt-tb.fcgi SearchScript mt-search.fcgi # XMLRPCScript mt-xmlrpc.pl ViewScript mt-view.fcgi # AtomScript mt-atom.pl # UpgradeScript mt-upgrade.pl
あとは, mt.fcgi にアクセスして, FastCGI で動作することを確認し, サイトをすべて再構築してやれば OK です.
これで負荷が減ってくれれば良いのですが...
MovableType を FastCGI で動作させる の続きを読む
ずいぶん前に, EC-CUBE の ML へ投稿した話題ですが, どうも過去ログに埋もれているので, 再度まとめてみます...
Windows Vista で, 日本語の文字集合に, JIS X 0213:2004(JIS2004) が採用されました.
このため, 扱える漢字が増えたり, 字体が変化したりして, さまざまな影響があります.
EC-CUBE を代表する PHP のアプリケーションや, Java の場合, どのような影響が考えられるでしょうか.
以前, Windows Vista での影響調査をする機会があり, いろいろ調べましたので, ちょっとまとめてみます.
文字のまとまりを規格化できるよう, 各文字に対して一連のコード(文字コード)を割り当てたものを「文字集合(文字セット)」と言います.
これには, Unicode や, JISX 0213:2004 などがあたります.
この文字集合をコンピュータで扱えるよう, 文字コードをバイトコードへ変換する仕組み(文字符号化方式)を文字エンコーディングと言います.
これには, Shift_JIS や, EUC-JP, UTF-8, UTF-16 などがあります.
文字コードと文字エンコーディングと文字セットを混同してしまいがちですが, それぞれの意味は別物です.
UTF-8 というのは, 正確に言うと Unicode という文字セットで規定されている文字エンコーディングの一つです.
Unicode における BMP(Basic Multilingual Plane)面とは, UTF-16 にて, 16bit のみで表現できる領域の文字のことを言い, 16bit + 16bit で表現する文字の範囲を 「サロゲート・ペア」と言います.
Unicode 以外の文字集合としては, UCS-4 (ISO/IEC 1064)という良く似た別物があり, UCS-4 で規定されている文字エンコーディングにも UTF-8 があったりします.
UCS-4 と Unicode は 21bit までの範囲で互換性があります. UCS-4 は4バイトを基本とし, 31bit までの領域を使用します. ややこしい...
一方, JIS X 0213:2004 では, 文字エンコーディングとして, ISO-2202-JP-2004, EUC-JP-2004, Shift_JIS-2004 などがありますが, IANA に登録されていないため, あくまでも参考となっています.
Windows Vista では, 使用する文字セットに, JIS X 0213:2004 を採用したため, UTF-16 でエンコーディングされる場合, BMP面以外の文字(16bit + 16bit で表現される文字)までサポートされることとなりました.
このため, UTF-8 でエンコーディングされる場合は, 1文字が4バイトで表現される文字も含まれます.
http://jp.php.net/mbstring を見るかぎりは, mbstring 関数を使用することで, サロゲート・ペアの文字が入力されても, うまく対応できそうです.
文字エンコーディングは, UTF-8 が無難でしょう.
http://www.mysql.gr.jp/mysqlml/mysql/msg/13823
これを見ると, DBエンコーディングに UTF-8 を使用した場合でも, 扱えるのは, 1文字3バイトまでの範囲に限られるようです...
つまり, Windows Vista で採用されたサロゲート・ペアの文字が入力された場合は, 確実に文字化けします(苦笑)
8.1.7以降、8.2.2以降であれば, UTF-8 で問題なく扱えるようです.
それ以前のバージョンは, 1文字4バイトで表現される文字を使用した場合に問題がでる可能性あります.
http://mlog.euqset.org/archives/pgsql-jp.ml.postgresql.jp/38404.html
Oracle は 10.1.0以降で対応とのことです.
char が 16bit であるため, 16bit + 16bit のサロゲート・ペアは正常に扱えません...
具体的には, String#length() や, String#substring() が正常に動作しません(苦笑)
プロパティファイルなど, \uXXXX で表わすものは 16bit なので, サロゲート・ペアの文字は使えません.
プロパティファイルを XML で書けば, 任意のエンコーディングを使用できるので, サロゲート・ペアの文字も使用できます.
Java でサロゲート・ペアの文字列を扱うには, Java SE 5.0 以降で追加された API を使います.
サロゲート・ペアが含まれる文字数を正確に数えるには,
文字列のソートとかも工夫が必要です. 手前味噌ですが, 下記にサンプルがあります.
http://d.hatena.ne.jp/nanasess/20070819/1187700166
http://itpro.nikkeibp.co.jp/99/vista/index.html
これを見ると, Vista で入力できても, XP 以前では対応していない文字が183字あり, この中には人名漢字も含まれます.
仮にWebアプリケーション側が Vista にフル対応したとしても, XP では表示できないというトラブルも発生します.
XP に JIS2004対応フォントをインストールしたりすることで回避できますが, 対応をクライアント側に任せるのもどうかと...
いちばん良いのは, Vista で問題の文字を入力した場合に警告を出すことでしょうかねえ...
今さらながら, Google Analytics のトラッキングコードを新しくしてみた.
こういう良くできたサービスの良いところをどんどん勉強し, 吸収していかなくてはなりません...
Life is beautiful: Born to codeそうやって愛しい我が子を育てる様にコードを一行一行書いていく
何百万人、何千万人もの人に使ってもらえる日を夢見ながら
プログラミングという楽しみがある時代に生まれて来ることができた幸せを噛み締めながら
前職が寿司屋の板前だった僕にとって, プログラミングというのは同じ職人気質の仕事.
多くの共通している部分があります.
違う部分は, ドキュメントを書くことかな...
板前は, 先輩の仕事を見て覚える.
エンジニアは, 後世のためにドキュメントを書く.
しかし, 現場が大規模化していったら, 職人の世界も同じようにドキュメントを書く能力が必要になってくると思います.
でも, 一番大切なのは, 「愛情」だと思っています.
料理に対して, いかに「愛情」を注げるか.
コードに対して, いかに「愛情」を注げるか.
チームに対して, いかに「愛情」を注げるか.
顧客に対して, いかに「愛情」を注げるか.
「愛情」を実感することが一番の幸せではないでしょうか.
職人のこだわり の続きを読む
最近のコメント