あ、これってべんりだなあって思ったコーディングのメモ。
AWS のLinuxでJavaを使う †ふつうにwgetでrpm取ってきて、あとはJavaの切り替え。 wget --no-check-certificate --no-cookies --header \ "Cookie: oraclelicense=accept-securebackup-cookie" \ http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c3b165be4555a1fa6e98c45e0808/jdk-8u161-linux-x64.rpm sudo rpm -Uvh jdk-8u161-linux-x64.rpm sudo alternatives --config java export JAVA_HOME=/usr/java/jdk1.8.0_161 ちなみにダウンロード先はこちら http://www.oracle.com/technetwork/java/javase/downloads/index.html HttpURLConnection での接続において、Proxyを越える(SSLも) †Jersey などライブラリを使ってる場合はこちら。。 JavaでSSLでRESTを投げるときに、プロキシを通す方法 - Qiita ピュア(?)のHttpURLConnection を使ってるときはこんな感じで行けそう*1 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)); final String authUser = "user"; final String authPassword = "pass"; Authenticator.setDefault( new Authenticator() { @Override public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication( authUser, authPassword.toCharArray()); } } ); System.setProperty("http.proxyUser", authUser); System.setProperty("http.proxyPassword", authPassword); HttpsURLConnection.setDefaultSSLSocketFactory( createSSLContext().getSocketFactory()); // setup a hostname verifier that verifies everything HttpsURLConnection.setDefaultHostnameVerifier(createHostNameVerifier() ); HttpsURLConnection con = (HttpsURLConnection)url.openConnection(proxy); // HttpURLConnection con = (HttpURLConnection)url.openConnection(); createSSLContext()、createHostNameVerifier?() メソッドは、上記サイトと同じモノを使います JavaでAWSのプロファイルを切り替える件 †AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() .withRegion(Regions.AP_NORTHEAST_1) .withCredentials(new ProfileCredentialsProvider("default")) ←プロファイル名 .build(); こんな感じ。 参考: http://www.masatom.in/pukiwiki/AWS/AWS%20CLI/#w1297a6a Mavenから AWS SDK for Java を使う場合 †Jerseyのエラー †org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class java.util.HashMap, genericType=class java.util.HashMap. ってエラーが出る場合。pom.xmlやクラスパスに、 <!-- jersyでJavaBeansをJSON でPOSTする場合。 --> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>${jersey.version}</version> </dependency> これが足りないから、かも! よく出てくるコマンド。 †Eclipseの設定。 mvn -DdownloadSources=true -DdownloadJavadocs=true eclipse:clean eclipse:eclipse Eclipse上からデバッグできるようにする export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n" SpringBoot?の起動 mvn spring-boot:run Jettyの起動 mvn jetty:run ファイルをつくる。 $ cat << __EOF__ >> output.txt > aaa > bbb > ccc > __EOF__ $ cat output.txt aaa bbb ccc もはやJava関係ないな。。 AWSのLinuxで Mavenを使う †AWSのLinuxで、速攻でMavenでビルドしたくなって、しらべた内容。ついでにJavacを切り替えるやり方まで。 Logの制御 †かつては Log4j がただ唯一の選択肢でしたが、どうやら乱立してるっぽい。そんなかでも多分コレがデファクト。 SLF4J経由でLogback。ついでにLombokでAnnotation。これで決まりかな。。 設定ファイルの制御 †ResourceBundle?を使った設定ファイルの制御について。ResourceBundle?ってpropertiesファイルで設定できるのみだと思ってたんですけど、どうやら設定情報(key/value)を返却するクラスを実装する機構があって、さらにその設定情報をpropertiesファイルで記述できる機能もある、って構造なんですね。。 下記のサンプルは設定情報をクラスパス上のプロパティファイルで設定できるようにしつつ、ファイルがなかった場合はデフォルト値を適用する、なんてケース。よくあるケースですね。ここで、デフォルト値は DefaultResources? クラスというListResourceBundle?を拡張したクラスを使用しています。 package nu.mine.kino.resourcesamples; import java.util.Enumeration; import java.util.ResourceBundle; import lombok.extern.slf4j.Slf4j; @Slf4j public class Main { public static void main(String[] args) { new Main().execute(); } // sample.properties をクラスパスから探して、なかったらデフォルト値を適用する。 // デフォルト値は、nu.mine.kino.resourcesamples.DefaultResources クラスで定義している。 private void execute() { String propertyFile = "sample"; ResourceBundle bundle = null; try { bundle = ResourceBundle.getBundle(propertyFile); doSettings(bundle); } catch (java.util.MissingResourceException e) { String message = "設定ファイルが存在しません。必要ならクラスパス上に {}.propertiesを配置してください。({})"; log.warn(message, propertyFile, e.getMessage()); doSettings(ResourceBundle.getBundle( "nu.mine.kino.resourcesamples.DefaultResources")); } } private void doSettings(ResourceBundle bundle) { Enumeration<String> keys = bundle.getKeys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); log.debug("key[{}]:{}", key, bundle.getString(key)); } } } package nu.mine.kino.resourcesamples; import java.util.ListResourceBundle; public class DefaultResources extends ListResourceBundle { @Override protected Object[][] getContents() { return new Object[][] { { "param1", "default value1" }, { "param2", "default value2" } }; } } sample.properties param1=property value1 param2=property value2 ファイルパスの操作(Java7版) †ファイルのパスをつなげるようなときに、もちろんStringでつなぐとかは論外として、、いままでは File base = new File("/tmp/base"); new File(new File(base, "more1"), "more2"); こんな風にくるんでくるんで、みたいな処理をしていたのが、 Paths.get("/tmp/base","more1","more2").toFile(); このように可変長引数を使ってつなげるようになりました。いまどきの言語だと当たり前なんですけど、Javaもキレイになりました。。 バイナリファイルをbyte配列に変換する(Java7版) †便利な世の中になりました。 try { byte[] bytes = Files.readAllBytes(Paths.get("パス")); } catch (IOException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } 自前で書く必要なくなっちゃいました。AutoCloseable?で自動でStreamをcloseしてくれてるし。 ある配列に配列を追加して新しい配列を作る †Object[] newArray = ArrayUtils.addAll(array1, array2); ある配列に単一のObjectを追加して新しい配列を作る †Object[] array = ...; Object element = ...; Object[] newArray = ArrayUtils.add(array, element); Commonsのデリミタで分割するヤツ †String[] splits = StringUtils.splitPreserveAllTokens(target, delimiter); StringBuffer?でカンマつなぎしたとき、最後のカンマはいらない件 †StringBuffer buf = new StringBuffer(); for (String str : array) { buf.append(str); buf.append(','); } buf.deleteCharAt(buf.length() - 1); return new String(buf); わすれがちな、Dateの比較 before/after †Date base = new Date(); Date target = base; System.out.println(base.after(target)); //おなじ日はfalse System.out.println(base.before(target)); //おなじ日はfalse System.out.println(base.before(DateUtils.addDays(target, 1))); // targetより前か → true System.out.println(base.after(DateUtils.addDays(target, -1))); // targetより後か → true 結果は false false true true バイト列を表示する。 †テキストファイルが文字化けしてて、どんなバイナリの値なんだろって確認したいときとかに、バイト列を取得し16進で画面表示するには以下のようにします。 private void printByte1(byte[] bytes) { String hexString = toHexString(bytes); System.out.println(hexString); } // byte[] -> 16進文字列へ変換 private String toHexString(byte[] b) { StringBuffer hexString = new StringBuffer(); String plainText = null; for (int i = 0; i < b.length; i++) { plainText = Integer.toHexString(0xFF & b[i]); if (plainText.length() < 2) { plainText = "0" + plainText; } hexString.append(plainText); hexString.append(" "); } return new String(hexString); } String#formatメソッドを使えば書式の指定で対応出来ますね。。 private void printByte2(byte[] bytes) { for (byte b : bytes) { System.out.printf(String.format("%1$x ", b)); } System.out.println(); } そもそもどうやってバイナリでファイル読むのっていうのは下記の通りやればできます。 ファイルをバイナリで読み込む。。 †定番はコレですかね String baseDirStr = "/tmp"; String fileName = "data.txt"; FileInputStream in = new FileInputStream(new File(baseDirStr, fileName)); int ch; while ((ch = in.read()) != -1) { // System.out.print(Integer.toHexString(ch) + " "); System.out.printf(String.format("%1$x ", ch)); } こういうのもある。。 RandomAccessFile accessFile = null; try { File file = new File(baseDirStr, fileName); accessFile = new RandomAccessFile(file, "r"); int length = (int) file.length(); byte[] bytes = new byte[length]; accessFile.read(bytes); printByte1(bytes); printByte2(bytes); } finally { if (accessFile != null) { accessFile.close(); } } RandomAccessFile? にはバイナリファイルを readDouble とかやって型を指定して取得できたりするので、まさにバイナリをファイルを読むときにはこっちが良さそうです。 テキストファイルをバイナリで読んでみるときとかは前者が良さそうです。 数値の文字列フォーマット変換 †doubleとかの数値をフォーマッティングした文字列を取得するメソッドです。こんな感じ。 String.format("%1$,.0f" + " KB中、" + "%2$,.0f"+ " KB処理しました。" + "%3$,.0f" + " %%処理完了", a / 1024.0, b / 1024.0, c / 1024.0); なかのプレースホルダは、それぞれ %1$ -> a / 1024.0 %2$ -> b / 1024.0 %3$ -> c / 1024.0 って可変長の引数に対応。さらに ,.0f で、「3ケタでカンマ区切り」「小数点以下は0ケタ」って意味。ちなみにフォーマット内で%を使う場合は、上記のように%%ってエスケープ。。 java.util.Date -> int †ついでに。。 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); <-2009/6/8に実行した int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(year); System.out.println(month); System.out.println(day); などで、Dateをintに変換可能です。 2009 5 8 Monthだけは日本人の感覚と一つ値がずれるので注意。 同様に、Calendar#set(int year, int month, int date) 、、具体的には Calendar calendar = Calendar.getInstance(); calendar.clear(); <-下で時分を指定しないから、clearしないと現在時刻が保持されちゃうので。 calendar.set(year, month, day); Date time = calendar.getTime(); とすることで、int -> java.util.DateもOKそうですね。 Calendar (Java 2 Platform SE 5.0) String -> java.util.Date †文字列からjava.util.Dateを生成する方法ですが、 Date parseDate = new SimpleDateFormat("yyyy/MM/dd").parse(date); System.out.println(parseDate); などとやればできますが、Commons Langの org.apache.commons.lang.time.DateUtils? をつかえばいくつかのフォーマットを同時に指定してDateを生成することができます。 Date date = DateUtils.parseDate(dateStr, new String[] { "yyyyMMdd","yyyy/MM/dd" }); 引数のパターンで順々にdataStrをパースして、Dateクラスを生成してくれます。 java.util.Date -> String †逆に、Dateから文字列を取得する方法。 String nowDateString = DateFormatUtils.format(nowDate, "yyyy/MM/dd"); System.out.println(nowDateString); フォーマットの指定の仕方によって、年を取得、月を取得、日付を取得、とかができますね。 「日」より下を切り捨てたDateを取得する †日付だけ管理したいんだよなぁってときがよくありますが、DateUtils? はその要求に応えてくれます。 Date nowDate = new Date(); System.out.println("Today: " + nowDate); // 「日」より下を切り捨て Date dateTruncate = DateUtils.truncate(nowDate, Calendar.DAY_OF_MONTH); System.out.println("Today: " + dateTruncate + " <-「日」より下を切り捨て"); // 「月」より下を切り捨て dateTruncate = DateUtils.truncate(nowDate, Calendar.MONTH); System.out.println("Today: " + dateTruncate + " <-「月」より下を切り捨て"); // 「年」より下を切り捨て dateTruncate = DateUtils.truncate(nowDate, Calendar.YEAR); System.out.println("Today: " + dateTruncate + " <-「年」より下を切り捨て"); 結果は以下の通り: Today: Mon Jun 08 10:00:54 JST 2009 Today: Mon Jun 08 00:00:00 JST 2009 <-「日」より下を切り捨て Today: Mon Jun 01 00:00:00 JST 2009 <-「月」より下を切り捨て Today: Thu Jan 01 00:00:00 JST 2009 <-「年」より下を切り捨て stackTraceを取得する †標準エラーに出力するならe.printStackTrace?()ですが、文字列として取得したい場合は、ストリームにスタックトレースを出力します。 private String exception2String(Exception e) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(baos)); return baos.toString(); } 文字コードとか大丈夫だっけとかありますが、こんな感じでできます。 プロパティファイルから、複数のデータを配列で取得する †Java Collections Framework の org.apache.commons.collections.ExtendedProperties? を用いると、
上記データにアクセスするサンプルコードは以下の通り。 ExtendedProperties props = new ExtendedProperties(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); InputStream resourceAsStream = loader .getResourceAsStream("hoge.properties"); InputStream in = new BufferedInputStream(resourceAsStream); props.load(in); String[] dataArray = props.getStringArray("data"); などとしてデータを取り出すことができます。
パイプされた標準入力を取得する †そういえばJavaって標準入力をどう受け取るんだっけ??ということで調べたメモ。パイプされた標準入力をechoするサンプル。 package nu.mine.kino.mail.utils; import java.io.BufferedInputStream; import java.io.IOException; public class Echo { public static void main(String[] args) { BufferedInputStream in = new BufferedInputStream(System.in); try { int size = in.available(); byte[] bytes = new byte[size]; in.read(bytes); System.out.println(new String(bytes)); } catch (IOException e) { e.printStackTrace(); } } } 結果はたとえば [hogehoge@www Test]$ ls | java -cp lib/sample.jar nu.mine.kino.mail.utils.Echo build.win.properties build_jar.xml classes lib source [hogehoge@www Test]$ lsの結果を受け取り、echoできました。
ちなみに標準入力を待ち受けてるときに入力完了を通知するための終了文字は Platform-Specific Details: The End-of-Input Character に書いてありました。 参考 Apache Axis 1.4のSSL処理にはバグがありそう †詳しくはまた時間がとれたらにしますが、Basic認証するプロキシサーバ越えでSSL通信するときのAxisの挙動がヘン。Axisが生成する Proxy-Authorizationヘッダの改行コードがおかしい模様。HTTPSの仕様的には、ほんとは\r\nが推奨されるらしいけど\nしかないため、まれに解析に失敗するプロキシサーバがあるようです。 BigDecimal?のコンストラクタにdoubleは使わないほうがいい †ちゃんと数値計算しようと思って、doubleとかの代わりにBigDecimal?を使ってたんだけど、やっぱ誤差が出ちゃう。何でだろーと思ってたら、BigDecimal?のコンストラクタでStringでなくdoubleを使ってたからでした。doubleを引数に取るコンストラクタの方は、引数自体が誤差が出ちゃってるから、正確な計算ができないって事ですね。素直にStringを使ったところ、ビシっと計算が合いました。 って、よく見たらJavaDoc?にも書いてありますね。 classesディレクトリを一括で削除するワンライナー †rm -rf `find ./ -type d -name classes` ファイル <-> byte[]に変換するUtil †import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; /******************************************************************************* * Copyright (c) 2007 Masatomi KINO. All rights reserved. * $Id$ ******************************************************************************/ public class Utils { public static byte[] file2Byte(String file) throws IOException { InputStream in = null; byte[] pix = null; try { in = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int j; while ((j = in.read(b)) != -1) { baos.write(b, 0, j); } pix = baos.toByteArray(); } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return pix; } public static void byte2File(byte[] b, String outputFile) throws IOException { BufferedOutputStream stream = null; try { File file = new File(outputFile); FileOutputStream fstream = new FileOutputStream(file); stream = new BufferedOutputStream(fstream); stream.write(b); } finally { if (stream != null) { try { stream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } } 整数を16進や2進で表示する †System.out.println(Integer.toHexString(15)); System.out.println(Integer.toBinaryString(15)); 実行結果は以下の通り。 f 1111 Base64でエンコードする †Base64とはE-mailなどバイナリデータを使用できない環境で、バイナリデータを扱うためのエンコード方式です*2。バイナリデータをテキストデータに可逆変換します。 Commons Codecを用いれば、バイナリデータを簡単にBase64エンコード可能です。 public class Base64Main { public static String encode(String input) { byte[] bs = Base64.encodeBase64(input.getBytes(), false); // booleanはある単位で改行を入れるかどうか return new String(bs); } public static void main(String[] args) { String string = encode("kino"); System.out.println(string); } } 実行結果は以下の通り a2lubw== 簡単ですね。引数にbyte[]を取るので、バイナリファイルからbyte[]を作成し、メソッドに渡してあげればバイナリファイルも簡単にエンコード可能なわけです*3。 ちなみにこのCodecライブラリは下に出てくる byte[] -> HexString?な変換をするメソッドなどもあります。 new String(Hex.encodeHex(b)); とすればOKです。 あ、よく見たらSHA-1でハッシュするメソッドもありました。 System.out.println(DigestUtils.shaHex("kino".getBytes())); でしたと同じ結果を得ることができます。実行結果は以下の通り。 c108a2616c020deeb71df83906f039e3dfcc6752 おなじですね。 SHA1でハッシュ化 †SHA-1はパスワードのハッシュ化などに使われるアルゴリズムです*4 public static String encrypt(String input) { try { MessageDigest md = MessageDigest.getInstance("SHA1"); md.update(input.getBytes("MS932")); return toHexString(md.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } private static String toHexString(byte[] b) { StringBuffer hexString = new StringBuffer(); String plainText=null; for (int i = 0; i < b.length; i++) { plainText = Integer.toHexString(0xFF & b[i]); if (plainText.length() < 2) { plainText = "0" + plainText; } hexString.append(plainText); } return new String(hexString); } public static void main(String[] args) { String string = encrypt("kino"); System.out.println(string); } 実行結果は以下の通り。 c108a2616c020deeb71df83906f039e3dfcc6752 SHA1でハッシュ化できました。MessageDigest?.getInstance("SHA1");の「SHA1」を「MD5」にすればMD5でハッシュ化できます。 java.lang.ThreadLocal?について †thlocal.set( new LegacySystemImpl2()); thlocal.set( new LegacySystemImpl()); LegacySystem impl = (LegacySystem) thlocal.get(); などと同じ型のクラスをセットした場合、どうも上書きになるっぽい。ソースを調べた分けじゃないけど。。 http://www.hyuki.com/dp/dpinfo_ThreadSpecificStorage.html#i1 Eclipseのヒープとタスクマネージャの関係 †Eclipseのヒープサイズと、タスクマネージャのjavawのメモリ使用量の関係。Eclipseのヒープが 1024M中の500M とかなってる場合、1024Mの方がタスクマネージャ上に表示される。だから実際どれだけjavaプロセスがメモリを使用しているかはOSからはわからないみたいですね。 EclipseでCVSのブランチを取り扱う。 †CVSのトランク(メインっていう?)とブランチをマスターしたくちょっと触ってみました。 まずはバージョンとしてタグ付け。タグ名はたとえば V20061026_01 とする。次にブランチの作成。チーム >> ブランチ より作成。ブランチ名はたとえば V20061026_01_BRANCH とする。そのとき、ブランチをマージするための開始点のタグも併せて登録される。これは自動的に Root_V20061026_01_BRANCH というタグ名になる。メインのモジュールにブランチをマージするには、開始点ってのが重要みたいだ。 ここまででCVSには上の3つのタグ V20061026_01 メイン側 V20061026_01_BRANCH ブランチ側 Root_V20061026_01_BRANCH メイン側 ができる。 Eclipseプロジェクトに、メインとブランチ両方落としておく。ブランチの方はプロジェクト名を_branchとかつけとく。 Eclipseで各プロジェクトでソースを修正してコミットする。 メイン側はバージョンは 1.1 -> 1.2 ブランチ側はバージョンは 1.1 -> 1.1.2.1 となるみたい。 さあ、ブランチからメインへマージします。メインのプロジェクトで、チーム >> マージを選択し マージされるバージョン(終了タグ) をブランチのバージョン i.e. V20061026_01_BRANCH 共通基本バージョン(開始タグ) をさっきの開始バージョン i.e. Root_V20061026_01_BRANCH と選択すると、左がメイン、右がブランチのソース比較画面が現れます。適宜Updateすればブランチのソースがメインに取り込まれます。後はメインにコミットすれば、ブランチ分のマージは完了です。 ※これはローカルコピーに、開始タグと終了タグの差分を取り出すって事かな?実際ブランチ側でマージしようとしたら、V20061026_01_BRANCH とV20061026_01_BRANCH には差分がないっていう当たり前の表示になってしまった。 実行中のメソッド名を取得する。 †new Throwable().getStackTrace()[0].getMethodName(); 何故これでメソッド名が取れるんだろう。。。でもうまくいきますねー byte配列をバイナリに変換する。 †逆に、byte[]をファイルに書き出す方法 public static void write(byte[] b) { BufferedOutputStream stream = null; try { File file = new File("after.bin"); FileOutputStream fstream = new FileOutputStream(file); stream = new BufferedOutputStream(fstream); stream.write(b); } catch (IOException e) { e.printStackTrace(); } finally { if (stream != null) { try { stream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } バイナリファイルをbyte配列に変換する †Webサービスでバイナリをアップするときなどは、byte[]で渡すみたいです。 public byte[] createBin() { InputStream in = null; byte[] pix = null; try { in = new FileInputStream("before.bin"); <-バイナリファイル ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int j; while ((j = in.read(b)) != -1) { baos.write(b, 0, j); } pix = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return pix; } Apache Axisで、プロキシーを越える。 †Apache Axisを使ったWEBサービスのProxyクライアントで、HTTPのプロキシー(ややこしい)を越える方法を探していました。 いやあEclipseでソースにブレークポイントつけまくって、探したー。。。。どうやら、 org.apache.axis.components.net.DefaultHTTPTransportClientProperties てクラスが、なにやらプロパティをセットしていて、そこがAxisの環境設定値になってる模様。そしてこのクラスは、org.apache.axis.AxisProperties?というjava.util.Properties みたいなのを使っている。ソースを見ると、httpプロキシを越えるためのキー値は AxisProperties.setProperty("http.proxyHost", "proxyのサーバ名"); AxisProperties.setProperty("http.proxyPort", "proxyのポート番号"); AxisProperties.setProperty("http.proxyUser", "xxxx"); AxisProperties.setProperty("http.proxyPassword", "xxxx"); 越えた。。キター。。。 Apache Axisで、自己署名証明書を使用してSSLさせる方法 †すげー HSQLDBの起動、フロントエンドの起動 †
ブラウザのCookieを手軽に参照する †JavaのTIPではないけど、J2EE開発中によく使うので。ブラウザのURLに javascript:document.cookie; と入力すると、クライアントのCookie(今開いているサイトに対するもののみ)を参照できます。 Jakarta Commons Langのいろいろ †Jakarta Commons LangはJavaのライブラリだけでは足りないようなユーティリティ的な機能を提供するクラスライブラリです。たとえば、こんな感じで使うことができます。
フィールドをカプセル化する †設定ファイルとかの場所がフィールドに定数で埋め込まれていて、単体テストのときだけそのパスを変えたいなあなんてときがあります。最近はDIとかで変えれるようにするのがはやってますが、DIコンテナなども使ってないときなどはどうすればよいでしょうか。 例としてテスト対象クラスがHogeだとして public class Hoge{ private String path ="hoge/hogehoge.properties"; ..... public void exe(){ new File(path).....; } } なんてのがあるとき、どうすればよいかってことです。 この場合、まずはソースを変更して単体テストしやすくします。そのソースの変更はEclipseなどを用いて、きっちりやる、と。やる手順は
具体的には上のクラスは以下のように変更します。
ってところですね。。ソースの変更に関してはEclipseなどで論理的に安全に行うことはできますが。手順は、 変数を参照している箇所(new File(path)の"path")を選択して、リファクタリング >> フィールドのカプセル化 定数がフィールドにすらいない場合は、上の前にさらにこれをやる 変数を選択して、 リファクタリング >> ローカル変数を フィールドに変換 プレースホルダを使う †MessageFormat?を使うと、{0}のようなプレースホルダを使うことができます。 SimpleDateFormat yyyy = new SimpleDateFormat("yyyy"); SimpleDateFormat MM = new SimpleDateFormat("MM"); SimpleDateFormat dd = new SimpleDateFormat("dd"); Date selectedDate = new Date(); String year = yyyy.format(selectedDate); String month = MM.format(selectedDate); String date = dd.format(selectedDate); Object[] dateArgs = { year, month, date }; MessageFormat form = new MessageFormat("{0}年{1}月{2}日"); <-プレースホルダ System.out.println(form.format(dateArgs)); 実行結果は 2005年03月18日 e.printStackTrace?()の文字列を取得する、出力先を変更する †例外のインスタンスをexとして StringWriter stringWriter = new StringWriter(); ex.printStackTrace(new PrintWriter(stringWriter)); String message = stringWriter.getBuffer().toString(); WSAD5.1.2でサーバの設定が格納されているディレクトリ †${WORKSPACE}\.metadata\.plugins\com.ibm.wtp.server.core\configs プロクシ認証などなど †-Dhttp.proxyHost=[プロクシサーバ名] -Dhttp.proxyPort=[ポート番号] -Dhttp.proxyUser=[UserID] -Dhttp.proxyPassword=[password] privateなフィールドにアクセスする †たとえばインスタンス名instance のフィールド(Stringで変数名aField)にアクセスするには Class clazz = instance.getClass(); Field field = clazz.getDeclaredField("aField"); field.setAccessible(true); String answer = (String)field.get(instance)); で取得できる。ここが参考になりました。 <%@ page %> タグ内の意味。 †たとえば <%@ page contentType=text/html; charset=EUC-JP" pageEncoding="Shift_JIS" %> とした場合、pageEncodingがソースコードの文字コード、contentTypeで指定できるのが出力文字コードです*5。この場合はソースをShift_JISで書いて、EUC-JPで出力するってことですね。 key=value&...の形式ではないPOSTリクエストの電文を取得する方法 †requestからReaderを取得して、そこから文字を取得すればよいわけですね。 BufferedReader reader = request.getReader(); StringBuffer buffer = new StringBuffer(); String line = null; while ((line = reader.readLine()) != null) { buffer.append(URLDecoder.decode(line)); buffer.append("\n"); } String reqMsg = new String(buffer); DOM2String †ByteArrayOutputStream out = new ByteArrayOutputStream(); try { TransformerFactory tfactory = TransformerFactory.newInstance(); Transformer transformer = tfactory.newTransformer(); transformer.setOutputProperty("encoding", encoding); transformer.transform(new DOMSource(document), new StreamResult(out)); } catch (TransformerConfigurationException e) { logger_.error(e); } catch (TransformerException e) { logger_.error(e); } return out.toString(); String2DOM †例外処理はとりあえずおいといて DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); StringReader stringReader = new StringReader(str); <- str: xmlの文字列 InputSource inputSource = new InputSource(stringReader); return builder.parse(inputSource); <- Document ファイル書きだし(バイナリで) †private void streamToFile(InputStream in, File file) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int j; while ((j = in.read(b)) != -1) baos.write(b, 0, j); byte[] pix = baos.toByteArray(); write(pix, file); } private void write(byte[] b, File file) { BufferedOutputStream stream = null; try { FileOutputStream fstream = new FileOutputStream(file); stream = new BufferedOutputStream(fstream); stream.write(b); } catch (IOException e) { e.printStackTrace(); } finally { if (stream != null) { try { stream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } ファイル書きだし(テキスト) †public boolean write(String log) { BufferedWriter writer = null; try { //第二引数がtrueなら追記、falseなら上書き。 writer = new BufferedWriter(new FileWriter("./log.txt", true)); writer.write(log, 0, log.length()); writer.newLine(); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } finally { try { if (writer != null) { writer.flush(); writer.close(); } } catch (Exception e) { e.printStackTrace(); } } return true; } あるディレクトリからの相対パスを計算して、他のディレクトリに連結したい。 †うまく説明できませんが、別のディレクトリに同じパス構成をコピーしたいときなどに使用できると思います。 //たとえば "c:/temp", "c:/temp/fuga/aaaaa.txt", "d:/huge/hoho" に対して // d:/huge/hoho/fuga/aaaaa.txt としたい public static String trimAndConcat(String base, String path, String other) { URI uriBase = new File(base).toURI(); URI uriPath = new File(path).toURI(); URI uriRelativised = uriBase.relativize(uriPath); return new File(other, uriRelativised.toString()).getAbsolutePath(); } URLからファイルパスへ。 †URLクラスからそのファイルまでのパスを取得する方法です。 String path = new File(url.getPath()).getPath(); とやることで、 URL : file:/C:/hoge/config/hoge.txt File: C:\hoge\config\hoge.txt (たとえば)拡張子がxmlのファイルをリストする †File mainDirectory = new File([ディレクトリ]); String[] files = mainDirectory.list(new FilenameFilter() { public boolean accept(File dir, String name) { if (name.endsWith("xml")) { return true; } return false; } }); filesが拡張子がxmlのファイル(ファイル名、の配列) 拡張子より後ろの文字列を取得する †String hoge="aaa.xml"; hoge.substring(hoge.lastIndexOf('.')); で.xmlが取得できる。 拡張子より前の文字列を取得する †String hoge="aaa.xml"; hoge.substring(0, hoge.indexOf('.')); でaaaが取得できる。/etc/aaa.xml.bakとかには使えないけど。。 Javaから、WEBブラウザを起動(Windowsのみ) †try { Runtime.getRuntime().exec( new String[] { "rundll32.exe", "url.dll,FileProtocolHandler", "http://jp.sun.com/" }); } catch (IOException e) { e.printStackTrace(); } SWTから起動したい方は こちら WEBアプリケーションのルートを取得してパスを生成する †String root_path = this.getServletContext().getRealPath("/"); String file_path = root_path + "hoge.dat" DOMオブジェクトをファイルに書き出す †try { TransformerFactory tfactory = TransformerFactory.newInstance(); Transformer transformer = tfactory.newTransformer(); // transformer.setOutputProperty("encoding", "EUC-JP"); transformer.transform(new DOMSource(document), <-document : XMLのDOMです //new StreamResult(System.out)); <- こっちだとコンソール出力 new StreamResult(new FileOutputStream(new File(output)))); } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerFactoryConfigurationError e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } catch (FileNotFoundException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } JSPやServletのOutにDOMを書き出したい。 †public void write(HttpServletRequest request, HttpServletResponse response) { response.setContentType("text/xml; charset=UTF-8"); try { PrintWriter out = response.getWriter(); transformer.transform(new DOMSource(getDocument()), new StreamResult(out)); } catch (IOException e) { } catch (TransformerException e) { } } Servletで、コンテンツタイプを指定する。 †response.setContentType("text/xml; charset=UTF-8"); プロキシ越えとか、HttpConnection? †//プロキシ認証の記述方法 BASE64Encoder encoder = new BASE64Encoder(); urlConnection.setRequestProperty( "Proxy-Authorization", "Basic " + encoder.encode((userid + ":" + password).getBytes())); javaの実行 †>java -classpath ".;lib;classes;lib\log4j-1.2.8.jar;swt.jar" kino.swt.JavaDocSearchForm >java -classpath ".;lib;classes;lib\log4j-1.2.8.jar;swt.jar;lib\kino_javadocsearch.jar" kino.swt.JavaDocSearchForm >java -classpath "クラスパス(セミコロン区切り)" クラス このサイトよいかも。 Javadoc書き方 †@see UserInformationManager#getUserInformation(String) とすると、リンクが張られる。 {@link InformationController InformationController}のファイル読み込みの実装です。 とか {@link クラス名#メンバ名 表示テキスト} なんて使い方もできる コレクションを配列に変換 †type: 型 collection: コレクションクラス (type[]) collection.toArray(new type[collection.size()]); 配列をコレクションに変換 †fileList: Object[]型 java.util.Arrays.asList(fileList); ファイルを読み込む †BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(path)); //もしくは //new BufferedReader( // new InputStreamReader(url.openStream(), "JISAutoDetect")); String line; while ((line = reader.readLine()) != null) { buffer.append(line); buffer.append("\n"); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.print |