投稿

9月, 2018の投稿を表示しています

Java : Java でUnicode文字列処理中に「�」という表示が出てくる現象。Replacement Character。

根本原因 *ブログのラベルは「Java」としましたが、「Unicode」「文字コード」と置くのが正確ですが、まぁそのへんはもう暗黙の前是ということで。 Unicodeにおいて、なんらかの文字コードでマッピングが失敗する場合、その取扱いできない文字は「�」(U+FFFD)に置換されます。 プログラム内の文字列処理中にこの状況になると、当然「�」になってしまいます。 詳細は自分が説明するよりも、とても詳しいブログがあったので、ぜひそちらを → 「 あしのあしあと : Javaにおける文字コード周りの話(5) 」 自分が遭遇した状況 MySQLで、どこかのフィールド値が「NUL文字」(U+0000)の場合、これを取得すると「�」になっていました。 [テーブル状況(簡易)] id str 1 あいうえお 2 かきくNULLNULL ↑をDAOなどでゲットすると、「1 : あいうえお、2 : かきく��」。 対応 U+0000以外にも同様の対応が必要な文字はあるので、とりあえずcharとして取扱い、OK/NG判定したりしました。 この辺はプロジェクトの状況ごとに対応するしかないと思います。

Servlet : 最近のサーブレット定義ではweb.xmlで外部参照ができなくなっています。

Servlet2とかの時代、web.xmlでは外部xml参照が可能であった。 こういう状況 → Google検索「 webxml entity 」 これらは、昨今のセキュリティ事情に合わせて使用不可となっている。(2015年ぐらい以降) 参考 : https://bugzilla.redhat.com/show_bug.cgi?id=1069911 脆弱性としては XXE attack で、外部xmlを任意のファイルで成りすまして悪さをするというもの。 いわゆるDLLハイジャックと同じ考え方。 ■ 以前はOKで、最近は読み込めなくなっている具体例 どういうコードがNGかというと、こんなタイプ↓ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app [ <!ENTITY test0 SYSTEM "aaa/test0.xml"> <!ENTITY test1 SYSTEM "aaa/test1.xml"> ]> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <!-- サーブレット設定 --> &test0; &test1; </web-app> これは、xmlパース時にエラーとなる。 以下、エラーログ↓ org.apache.catalina.startup.ContextConfig parseWebXml 重大: アプリケーションのweb.xmlファイル jndi:/localhost/xxx

Java : [標準API]Map<String,Object>型を JSONパース可能な1行のString型に変換。

標準APIのみで、Map<String,Object>(最終的にはMap<String,String>)を、JSONのパースが可能な1行の文字列に変換する再帰関数。 Java1.8。 以下コード。 /** * Map 型をJSONパース前のString平坦文に変更。 * @param map : Map<String,Object>型で定義されている。終端の要素はMap<String,String>であってほしい。 * @return 引数 map をString型に変換した状態。 */ @SuppressWarnings("unchecked") private String mapToString(Map<String, Object> map) { String sss = "{"; for (Entry<String, Object> e : map.entrySet()) { if ( e.getValue() instanceof Map ) { sss += "\"" + e.getKey() + "\":"; sss += mapToString((Map<String, Object>)e.getValue()); sss = sss.substring(0, sss.length() - 1) + "},"; } else { sss += "\"" + e.getKey() + "\":\"" + e.getValue() + "\","; } } return sss.substring(0, sss.length() - 1) + "}"; } こういう状況なら、JavaScrirptで以下のような取扱いが可能。 var j = JSON.parse(sss)

JavaScript : 自分のWebコンテンツ配下のローカルファイルを読み込む

今どきの色々なライブラリを使えないような状況で、 どうしてもローカルファイルを読み込む必要があるときのJavaScriptコードです。 XMLHttpRequest を使用して読み込みましょう。 Chrome、Firefox、IEで共通です。 *Webコンテンツ外のC:ドライブのどこか~などを指定するわけではありません。 ■準備 例えばこんなディレクトリ構成だったとして。 WebContent css data target.json img js jsp WEB-INF classes ... ■コード例 下記例ではjsonファイルを読み込んで、関数内でパースします。 // JSONファイルの読み込み。 function readJSON(){ var f = "data/target.json"; var retJson; var obj = new XMLHttpRequest(); obj.open( 'get', f, false ); //ファイルオープン : 同期モード obj.onload = function() { try { retJson = JSON.parse(this.responseText); //JSON型でパース。 } catch (e) { alert("コマンド定義ファイルの読み込み、解析に失敗しました。"); } } obj.send(null); //ここで読込実行。 return retJson; } ちなみに、WebContent外のファイルは流石に読み込めないと思います。

Java : ServletConfig::getInitParameter()で引数がnullの場合、APサーバーによって挙動が異なる。

例えばこういう状況。 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp){ String s = getServletConfig().getInitParameter(null); 普通はあんまり考えられませんが、あったとして。 環境が変われば挙動も変わるという、当たり前のことなのですが、いちおう軽く確認しました。 何かのお役に立てれば。 Tomcat6 : null が返却される。 Tomcat9 : NullPointerException がスローされる?(*未検証) Wildfly10 : IllegalStateException がスローされる。 以下でざっくりと補足。 ■Tomcat6 null が返却される。 挙動としてはHashMapのnullの挙動と同じ。内部ではきっとこうなってるんじゃなかでしょうか。 //HashMapのnull指定時の挙動テスト。 HashMap map = new HashMap (); try { String s = map.get(null); System.out.println(s); } catch ( Exception e ) { System.out.println(e.getMessage()); } ■Wildfly10 IllegalStateException がスローされる。 /** * Returns a String containing the value of the named * initialization parameter, or null if the parameter does * not exist. See {@link ServletConfig#getInitParameter}. * * This method is supplied for convenience. It gets the * value of the named parameter from the servlet's * ServletConfig object. * * @param

ExcelVBA : 表示されない名前の管理を出すマクロ

企業内で長い期間使い回されてきたエクセルは、数式->名前の管理がぐちゃぐちゃになりがちで、 結果、ファイルサイズは肥大し、シートをコピーするとよくわからない確認ダイアログボックスが出現して煩わしいです。 画面から全部消したと思っても、状況は改善されない。 という状況で使うマクロ。 見えていない名前の定義が出てきます。 出現させたあとはエクセルのリボンで、数式 -> 名前の管理 で不要分を削除するとよいでしょう。 Public Sub DisplayNames() Dim o As Object For Each o In Names o.Visible = True Next End Sub

Java : processbuilder 標準出力 タイムアウト

( 1つ前の投稿 から続けて) Java(1.8)で外部シェルを実行するというお話、その2。 いったん作成したが、「タイムアウトとかほしいよね」とのことでタイムアウト判定を入れることになった。 単純にタイムアウトだけであれば タイムアウト付きwaitFor() が使えたと思う。 ただ、この関数は標準出力バッファが詰まった時点で、エラー扱いで処理が戻ってきた。 理想のタイムアウトの挙動は以下であった。 タイムアウトになるまではずーっと標準出力を受け取っていてほしい。 タイムアウト時点で、そこまでの標準出力を全部受け取っていて、最後に「と、ここまでやったけど、ここでタイムアウトしました」ぐらいの結果返却。 というわけで、前回の「標準出力バッファを吸い出しながら処理するコード」を元にして、タイムアウト処理を追加する形で実装。 コードは以下。 ちなみに、タイマーに内部クラスを使用しているのは好みです。 当然、System.currentTimeMillis() と if文でも同様のことが出来ますし、ここでは一つの例ということで。 // cmd[] は とりあえずこんな → [0]:ユーザー用コマンド名称、[1]:処理開始日時、[2]:外部実行のシェル名、[3]~ : 引数情報(可変長) private List&ltString&gt cmdExecute(String[] cmd) throws Exception { // タイムアウト用タイマー : 内部クラス class CmdTimer extends TimerTask { private boolean isTimeout = false; private Process p = null; public CmdTimer( Process p ) { this.p = p; } public boolean getIsTimeOut() { return this.isTimeout; } @Override public void run() { this.isTimeout = true; try {

Java : processbuilder 標準出力

Java(1.8)で外部シェルの実行を行うお話。 シェルはけっこうな数が存在し、標準出力として「正常(異常)終了しました」と出力するものや、各種のステータスを一覧形式で出力するものがあった。 この時、標準出力が多くなると、文字数によってはバッファが詰まる状況となる。 というわけで、シェル実行中に細かくバッファから文字を吸い上げるプログラムとした。 参考にさせていただいたサイトはこちら。 ひしだま's 技術メモページ -> java -> 外部プロセス起動 以下コード。 // cmd[] は とりあえずこんな → [0]:ユーザー用コマンド名称、[1]:処理開始日時、[2]:外部実行のシェル名、[3]~ : 引数情報(可変長) private List&ltString&gt cmdExecute(String[] cmd) throws Exception { // 標準出力受け取り用の配列。 List&ltString&gt resultStr = new ArrayList&ltString&gt(); resultStr.add("Command start time [" + cmd[1] + "]"); resultStr.add("========================================"); resultStr.add(""); // ■準備 ProcessBuilder pb = new ProcessBuilder(Arrays.copyOfRange(cmd, 2, cmd.length)); //配列は、シェル名、引数~ の順序で固定。 // 標準出力と標準エラー出力を同一視 pb.redirectErrorStream(true); // ■準備2 Process process = null; InputStreamReader isr = null; BufferedReader reader = null; try { // プロセススタート process =