JSPのお勉強-文字化け対策

先日に引き続き、JSPPostgresqlについて自分なりに調べたことの一部を書き留める。

今回はよくある「文字化け」について。

たとえば、テキストフォームに値を入力し、それを次の画面で用いることはよくあるはず。
しかし、2バイト文字を使って行おうとすると文字化けした。

それを解決するための手順を記す。

ちなみに、JSP内部で文字コードは以下の通りに指定した。(pageEncoding, charset*2)

<%@ page language="java" contentType="text/html; charset=windows-31j"
    pageEncoding="windows-31j"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=SHIFT-JIS">
   (以下略)

入力した値などは、Formのbuttonやsubmitを使って渡す。(ちなみに自分はbutton派)
特に問題はない。


そして受け取る側では、きっと以下のものを使ってる人もいるはず。(パラメータ:titleの場合)

request.getParameter("title") 

そこを、以下のように直すことで文字化けが解消された。

String setTitle = request.getParameter("title") 
setTitle = new String(setTitle.getBytes("8859_1"), "SHIFT-JIS");

SHIFT-JISの部分は、JSPで設定した文字コード次第で変わる。

これをする理由は、JSP文字コードをSHIFT-JISなどにしたとしても、パラメータの受け渡しはISO-8859-1で行われる。
なので、そのまま受け取るとJSPはSHIFT-JISと思って受け取るが、実際はISO-8859-1であるため文字化けが起きるらしい。
それを解消するために、ISO-8859-1からSHIFT-JISに変換するという作業を行っているようだ。

これを理解するの時間かかったなあ・・・


あと、研修中に聞かれることが多かったことは、JSPPostgresqlのレコードを読み込み・表示した際に、中のデータが2バイト文字だと文字化けが起きてしまうということ。

これを解決するためには、データベースを作る際の「エンコーディング」をUTF-8などに変更すること。
初期値がSQL_ASCIIであると、2バイト文字はまともに表示されません。

面倒くさいですねー

ってことで、今日はここまで


本日の教訓:「文字コードの設定は大切」

JSPのお勉強

前回JavaTwitterクライアントを作ろうとしていたが・・・
会社が忙しいので一時保留に
断じて行き詰って諦めたわけじゃないよ?本当だよ?


ってことで、会社でJSPの研修を行っていて、さっぱりわからないから土日にお勉強した。
とりあえず勉強したことをメモしておく。
今日はJSPPostgresqlの連携についてのみ書き留める。


環境はEclipse+jre1.6+Tomcat6.0+PostgreSQL8.3
JDBC Driverにはpostgresql-8.3-604.jdbc4.jarを使用

とりあえず、EclipsejreTomcatの設定を済ます。
そして、tomcatのlibフォルダの中にJDBC Driverをコピーしておく。←これをしないと、JSPでPosgreにアクセスできない。

また、jreのバージョンにも注意。jreが1.6じゃないとjdbc4が使えない?(勘違いの可能性も)

<%@ page language="java" contentType="text/html; charset=windows-31j"
    pageEncoding="windows-31j"%>
<%@ page import="java.sql.*, java.util.regex.*" %>




Title


データベースから読み込み

<% try { // PostgreSQL JDBC ドライバロード Class.forName("org.postgresql.Driver"); // PostgreSQL JDBC 接続 Connection db = DriverManager.getConnection("jdbc:postgresql:データベース名","ユーザ名","パスワード"); // PostgreSQL JDBC 問い合わせ SQL 作成 String sql = "select * from テーブル名"; //ステートメントを作成する Statement st = db.createStatement(); // レコードセットオープン ResultSet rs = st.executeQuery(sql); // 保存されている全レコードを読み込む while (rs.next()) { int id = rs.getInt("カラム名"); //一つ目のカラム(INT型) String name = rs.getString("カラム名2"); //二つ目のカラム(String型) String pass = rs.getString("カラム名3"); //三つ目のカラム(String型) out.println("

" + rs.getString(1) + " " + rs.getString(2) + " " + rs.getString(3) + "

"); //レコードを順に表示 } // PostgreSQL JDBC レコードセットクローズ rs.close(); // PostgreSQL JDBC ステートメントクローズ st.close(); // PostgreSQL JDBC 接続クローズ db.close(); } catch (Exception e) { // エラー処理 out.println("

error

"); } %>

とりあえず、これでデータベースに保存したレコードが一覧で表示される。
たったこれだけのことすら調べるのに時間が掛かった・・・
まあ、初めてだし仕方ないよね!
ってことで、明日も研修なので今日はここまで。


本日の教訓:「知識は宝」

twitterクライアント 〜TL取得編〜

苦手なJavaを勉強するついでに、twitterクライアントっぽいものを作ってみることに。

ちなみに開発環境は最近までやってた仮想マシン上にこちらeclipseを使用。すでに日本語化されてるし、他にも色々ある様子。便利便利

次にTwitter4JSWTをそれぞれダウンロードして、プロジェクトにJARの追加を行う。

一応今日試しに作ったのが↓のようなもの

以下ソース

package twitter.get;

import java.text.SimpleDateFormat;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;

public class TwitterGet {
	public static void main(String args) throws TwitterException {
		String twitterID = "togano";
		String twitterPassword = "教えてあげないよ!";
		int getPages = 2;          //取得ページ数(1〜10)
		
		Twitter twitter = new Twitter(twitterID, twitterPassword);
		List statuses = twitter.getFriendsTimelineByPage(1);
		for(int i=1; i statuses2 = twitter.getFriendsTimelineByPage(i+1);
			statuses.addAll(statuses2);
		}
		
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("TwitterGet");
		
		shell.setLayout(new FillLayout());
		Table table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION
				| SWT.BORDER);// ヘッダを可視にする
		table.setHeaderVisible(true);

		TableColumn nameCol = new TableColumn(table, SWT.LEFT);
		nameCol.setText("名前");
		nameCol.setWidth(60);
		TableColumn postCol = new TableColumn(table, SWT.LEFT);
		postCol.setText("投稿");
		postCol.setWidth(300);
		TableColumn dateCal = new TableColumn(table, SWT.LEFT);
		dateCal.setText("日時");
		dateCal.setWidth(130);
		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy'/'MM'/'dd' 'HH':'mm':'ss");
	    
	    for(Status status : statuses){
	      TableItem item = new TableItem(table,SWT.NULL);
	      String data = {status.getUser().getName(),status.getText(),
	                       String.valueOf(sdf1.format(status.getCreatedAt()))};
	      item.setText(data);
	    }
	    
	    shell.setSize(520, 500);
	    shell.open();		
	    while (!shell.isDisposed()) {
		if (!display.readAndDispatch())
			display.sleep();
		}
	    display.dispose();
	}
}

でも、絶対おかしいところがある。

		List statuses = twitter.getFriendsTimelineByPage(1);
		for(int i=1; i statuses2 = twitter.getFriendsTimelineByPage(i+1);
			statuses.addAll(statuses2);
		}

20個以上のタイムラインを取得する方法が分からないから、無理やりListを連結させてたり。
もっとスマートなやり方があるはず・・・誰か教えてください・・・

それ以上に、API制限回避して取得する方法を是非・・・
作ってる最中でいきなりエラー大量発生したから何事かと思ったら、ただのAPI制限だったっていうorz
非同期APIのサンプルで解決するのかと思って試したけどコンパイル通らないし
Javadoc読めば解決するのかなぁ でも英語がなぁ・・・
というか、こういう時にtry/catchを使うんだろうか?分かってないからこの辺の勉強も必要だ

とりあえず明日も会社で研修なので今日はここまで


最低限必要なTL取得周りの課題(暫定)
●API制限の回避手段
・TL自動更新
・未読/既読の目印
・Reply/Directの目印
・ソースを綺麗に!


本日の教訓:「英語は大切」



ちなみにオセロを作ろうとしたんだけど、マウスイベント辺りで詰まったから諦めたのは内緒><

仮想マシン 〜VMware Player編〜 part3

 前回でVMwareServerをインストールすることなく、無事に仮想マシンを作成することができた。あとはこれを運用するのみだが、快適に使うには微調整が必要。今回はこれをメモしておく。(ちなみに書き忘れてた?けど、ホスト・ゲストOSともにXPProを使用している) 
 とりあえず、仮想マシンにXPProをインストール。次に以前書いた通りにVMwareToolsを入れる。 ちなみにVMwareToolsで得られる恩恵は下のような感じ。これを入れなくては話にならない(と自分は思っている)。

・マウスカーソルの透過的移動 
・グラフィックパフォーマンスの向上
・共有フォルダ機能
・ドラッグ&ドロップ操作(WindowsOS間のみらしい)
・ホストOSとゲストOSの時刻の同期化
・ホストOSとゲストOS間のコピー&ペースト
・一部ゲストOSでのマウスパフォーマンスの向上?

 ここで一度起動中の仮想マシンをシャットダウンして、vmxファイルをテキストエディタで開くと下の項目が自動生成されているはず。ここで生成されるのが何を示すのか分からないのが半分ほど・・・

.encoding
ethernet0.addressType
tools.syncTime
uuid.location 
uuid.bios
virtualHW.productCompatibility
tools.upgrade.policy
ide0:0.redo
vmotion.checkpointFBSize
ethernet0.generatedAddress
ethernet0.generatedAddressOffset

 まずは共有フォルダを有効にさせるために以下を追記。

sharedFolder.maxNum = "1"             #共有フォルダの最大数
sharedFolder.option = "alwaysEnabled"       #有効期間
sharedFolder0.present = "TRUE"           #一つ目の共有フォルダの有無
sharedFolder0.enabled = "TRUE"                     # ゞ の有効・無効を指定
sharedFolder0.writeAccess = "TRUE"                 # ゞ の書き込みアクセス可否
sharedFolder0.readAccess = "TRUE"                  # ゞ の読み込みアクセス可否
sharedFolder0.hostPath = "C:\vmware\shareFolder"   # ゞ の場所を指定
sharedFolder0.guestName ="share"                   # ゞ のゲストOS内でのフォルダ名
sharedFolder0.eXpiration = "never"                 #
hgfs.mapRootShare = "TRUE"                         #共有フォルダをネットワークドライブでマウントするか否か
isolation.tools.hgfs.disable = "FALSE"       #共有フォルダ機能の有効・無効を指定(TRUE=無効)

 次に高速化のために下の部分を追記・変更

numvcpus="2"                    #CPU数。1か2が設定できるが、物理マシンのCPU以下であること。
mainMem.useNamedFile = "FALSE" #ゲストのメモリに実メモリを使用させる。

 最後に3Dアクセラレーションを有効にするために以下を追記

mks.enable3d = "TRUE"        #Direct3Dを有効にする。
svga.vramSize = "67108864"   #仮想マシンのビデオメモリサイズを指定する。
vmmouse.present = "FALSE"    #絶対ポインティング・デバイスを無効にする。

 ここで注意。D3Dを有効にするためにmks.enable3dとvmmouse.presentを上記のようにしたが、自分の環境ではそれぞれ不具合がでた。<3/28訂正 mks.enable3dの不具合は勘違い?急に使えるようになったので>

mks.enable3d = "TRUE" → 一度Direct3D対応のソフトを起動した後には、OS間でドラッグ&ドロップでのファイルコピーが出来なくなる模様。
vmmouse.present = "FALSE" → マウスカーソルの透過的移動がまともに動作しない。出来なくはないが、思い通りに動かない。

 mks.enable3d = "FALSE"にするとゲームが動かなくなるため、ドラッグ&ドロップは諦めることに。しかし、vmmouse.present = "FALSE"は下記のように無効にしても影響はなかった。(分からなかった)

mks.enable3d = "TRUE"
svga.vramSize = "67108864"
#vmmouse.present = "FALSE" 

 最終的に自分のvmxファイルはこんな感じに。(USBは使わないっぽいから無効化)

##### Environment #####
.encoding = "Shift_JIS"
config.version="8"
virtualHW.version="4"
displayName="XPPro"
guestOS="winxppro"
nvram="nvram"
logging="TRUE"
tools.syncTime = "FALSE"
uuid.location = "(環境依存?)"
uuid.bios = "(環境依存?)"
virtualHW.productCompatibility = "hosted"
tools.upgrade.policy = "manual"
vmotion.checkpointFBSize = "16777216"

##### CPU #####
numvcpus="2"

##### Memory #####
memsize="512"
mainMem.useNamedFile = "FALSE"

##### FDD #####
Floppy0.present="FALSE"

##### HDD #####
ide0:0.present="TRUE"
ide0:0.devicetype="disk"
ide0:0.filename="C:\vmware\xp.vmdk"
ide0:0.startConnected="TRUE"
ide0:0.redo = ""

##### CD/DVD #####
ide0:1.present="TRUE"
ide0:1.autodetect = "TRUE"
ide0:1.devicetype="cdrom-raw"
ide0:1.startConnected="TRUE"

##### Sound #####
Sound.present="TRUE"
Sound.virtualdev="es1371"

##### Ethernet #####
Ethernet0.present="TRUE"
Ethernet0.connectionType ="bridged"
ethernet0.addressType = "generated"
ethernet0.generatedAddress = "(環境依存?)"
ethernet0.generatedAddressOffset = "0"

##### USB #####
usb.present="FALSE"
usb.generic.autoconnect = "TRUE"
ehci.present = "TRUE" 

##### 3Dアクセラレーション #####
mks.enable3d = "TRUE"
svga.vramSize = "67108864"
#vmmouse.present = "FALSE"

##### Shared Folders ######
sharedFolder.maxNum = "1"
sharedFolder.option = "alwaysEnabled"
sharedFolder0.present = "TRUE"
sharedFolder0.enabled = "TRUE"
sharedFolder0.writeAccess = "TRUE"
sharedFolder0.readAccess = "TRUE"
sharedFolder0.hostPath = "C:\vmware\shareFolder"
sharedFolder0.guestName ="share"
sharedFolder0.eXpiration = "never"
hgfs.mapRootShare = "TRUE"
isolation.tools.hgfs.disable = "FALSE"

 他にも設定項目があったけど、必要を感じなかったor意味が分からなかったで放置。ちなみにこちらを参考にさせて頂きました。(他にも多く見回りましたが)
 とにかくこれで、安心・快適にゲームのプレイや新規ソフトウェアのインストールなどが可能となった。めでたしめでたし。
 最後に自分の環境を簡単に晒しとく

OS:Microsoft Windows XP Professional ServicePack3
CPU:Intel Core2Duo 6600 @2.40GHz
RAM:UMAX Pulsar DCSSDDR2-2GB-800 (DDR2 PC2-6400 1GB 2枚組)
M/B:ASUS P5B
VGA:LEADTEK WinFast PX8600GT

ゲストOS:Microsoft Windows XP Professional ServicePack3

 なんか無駄に多く書いたけど今回はこれまで。次は何を書こう?仮想マシンネタで何かあるかなー


 今回の教訓:「便利にするまでの手間が半端無い」

仮想マシン 〜VMware Player編〜 part2

 予定ではVirtualBoxについてメモする予定だったけど、すでに失敗した&アンインストールしてもう長いってことで取りやめ。そのうち改めて使うだろうから、そのときに書くとしよう。

 ということで、現在使ってる環境を先にメモしとく。前回書いたとおり、VMwarePlayerではD3Dが有効になりゲームも起動することができた。しかし、仮想マシンを作る機能がなく、そのためにServerをインストールするのは面倒くさい。そこで、Qemu on WindowsとVMX-Editorを使って作成する。

 まず、qemu-0.9.1-windowsVMX-Editorをダウンロードして解凍する。そしてvmx-editorb.exeを起動。
 まず、システム→環境設定を開き、先ほど解凍したフォルダの中にあるqemu-img.exeとVMwarePlayerのインストール先にあるvmplayer.exeをそれぞれ選択してOK。
 次に仮想マシンを作成する。VMの管理→ディスクの作成で仮想マシンの容量と保存先を選択し、作成ボタンを押す。(例:C:\vmware\xp.vmdk)
 最後にvmx(設定情報ファイル)を作成する。VMの管理→VMの作成→VMの作成ウィザードを開き、指示に従い進める。自分は以下のような感じ

名前:XPPro
保存先:C:\vmware:xp.vmx
ゲストOS:Windows バージョン:XP(Pro)
ネットワーク:Bridge接続
メモリサイズ:512MB
その他:動作ログの取得、USBデバイスの使用
仮想ハードディスク:C:\VMware:xp.vmdk
仮想ハードディスクを自動認識させる
CD-ROMドライブ:物理ドライブを使う
サウンドカードの種別:ES1371

 実際作成されたxp.vmxをテキストエディタで開くとこんな感じ。

# Made by vmx-editor
config.version="8"
virtualHW.version="4"
numvcpus="1"
nvram="nvram"
memsize="512"
displayName="XPPro"
guestOS="winxppro"
Ethernet0.present="TRUE"
Ethernet0.connectionType ="bridged"
logging="TRUE"
usb.present="TRUE"
usb.generic.autoconnect = "TRUE"
Floppy0.present="FALSE"
Sound.present="TRUE"
Sound.virtualdev="es1371"
ide0:0.present="TRUE"
ide0:0.devicetype="disk"
ide0:0.filename="C:\vmware\xp.vmdk"
ide0:0.startConnected="TRUE"
ide0:1.present="TRUE"
ide0:1.autodetect="FALSE"
ide0:1.devicetype="cdrom-raw"
ide0:1.startConnected="TRUE"

 これで、準備完了!あとはVMwarePlayerで作成したxp.vmxを開くと起動するのでOSをインストールすればOK!
 ってことで、続きはまた後日。次回、仮想マシンVMware Player編〜 part3に続く。


 今回の教訓:「ツール作成者への感謝を忘れずに」