出羽と発火後忘失

FIRE AND FORGET

MacのZipがWinで文字化けすることによって助かっている面もある

これらのリンク先では、Macの標準機能でZip圧縮した日本語名ファイルをWindowsで展開すると文字化けしてしまう、ということが書かれています。
また、理由として、 UTF-8 エンコーディングされたファイル名を CP932 とみなして処理しているからだ、という原因も書かれています。

では、例えばファイル名のエンコーディングを手動で指定できるようになれば、文字化けせずに展開できるので問題は全て無くなるのか、というとそういうわけでもない、という話です。

実際に試してみます。
JavaではZipファイルを扱うAPIがあり、デフォルトではファイル名を UTF-8 であるとみなして処理します。
このAPIを利用して次のようなプログラムを書きました。

続いて、Macの標準機能でファイルをZip圧縮しWindowsへ持ってきて上記プログラムで展開したファイルと、Windowsで作成した同名ファイルを並べたものが次のキャプチャです。
Windows7の、エクスプローラ上の表示とコマンドプロンプト上の表示です。

f:id:yukihaned:20170423164241j:plain

エクスプローラ上では、同名のようにみえるファイルが2つ並んで存在しています。通常では同名ファイルを同じディレクトリに入れることはできません。
コマンドプロンプト上では、一方は濁音の濁点が分離して表示されています。他方は通常どおりの表示です。

つまり、現状文字化けすることで異なっているものだと認識できていますが、これが正常に表示されるようになると、人間が見て判別不能な差異になってしまう、ということです。
いわゆる UTF-8-MAC 問題です。

Java9で新元号対応

2019年から元号が新しくなるというニュースがあり、関連してJavaで新元号対応するには…という話題も聞こえてきましたので私も調べてみました。
よく見かけたのは calendars.properties を編集する、というものでしたが、それとは異なる回答も出せそうなのでここに記載します。

まず、Oracle社の公式見解ですが、
元号(和暦) (Hiroyuki Yoshino's Blog):


元号が決定された場合、Java SEの最新リリースでの対応をお待ちいただくことになりますが、Googleなどで検索してみると、アプリケーション開発での独自の対応(calendars.properties ファイルの編集など)を考えている方もいらっしゃるようです。

ということだそうです。
ちなみにJava8のサポート期間は(現時点の予定では)2017年9月だそうなので、Java8で新元号サポートを受けるには有償契約が必要になりますね。

続いてJava9の事情ですが、次のようなIssueが挙がっていました:

コード差分を見ると次のような対応になっています:

  • calendars.properties に記述されていたデフォルト設定は削除され、LocalGregorianCalendarクラスにハードコードされるようになった。
  • 追加の設定はjdk.calendar.japanese.supplemental.eraプロパティで行うようになった。

つまり、Java9では、calendars.propertiesに新元号をセットすれば良い、というわけではなくなりそうです。現在多く流通している情報では対応できない、ということです。

早速OpenJDK9-ea(build152)をダウンロードしてこのIssueに付随していたテストケースを実行してみたところ、…あれ、失敗しました。
あらためて、リポジトリからとってきた最新ソースからビルドしたOpenJDK9でテストケースを実行すると…成功しました。
この辺のソース管理について理解していないのですが、まだEA版にはマージされてはいないようですね。

Java8 Stream ちょっと便利な終端操作

処理を行った結果、要素がちょうど1になっているはずだ、あるいは0か1となるはずだ、という実装を行うことが多いのでこんな終端操作を作ってみました。

に大きくインスパイアされております…!



gist1565cbb59dd79719cc3e94acc3863ddd

Apache POI をビルドしてMaven管理する

Apache POIを改変し自前でビルドしてMaven管理したのでその時の手順をメモしておきます。
(本来 build.xml 見れば分かることなのですが、Antのことなどこの先忘れる一方だと思うので…)

手順

  1. ant clean jar jar-src maven-poms
  2. build/dist/maven/poi-ooxml に配布用モジュールができますのでこのディレクトリに移動*1
  3. mvn -DpomFile=poi-ooxml-3.15.pom -Dfile=poi-ooxml-3.15.jar -Dsources=poi-ooxml-3.15-sources.jar install:install-file

その他メモ

  • AntとMavenは特に連動しているわけではない。依存ライブラリを追加する場合にはbuild.xmlにも追記する必要があるし、pomファイルにも追記が必要。
  • 文字コードはASCIIなので、例えば日本語でコメントを入れるとコンパイルエラーになる。
  • Java6

関連リンク

*1:今回はpoi-ooxmlを改変したかったのでこのような説明になっている。

Java8向けMaven quickstart archetype

https://github.com/yukihane/maven-archetype-java-quickstart

いつも mvn archetype:generate とやった後、java1.8向けにプロパティを設定したりJUnitのバージョンを書き換えたりしていましたが、さすがに面倒になってきました。
はじめからJava8向けに設定できないものか、と検索してみたところ、予想していた以上にarchetypeを自作するのは簡単でしたので、作ってみました。

README.md にも記載していますが、インストールするには以下のコマンドを実行します:

mvn clean install
mvn archetype:update-local-catalog

以後 mvn archetype:generate したとき候補リストの最下行に本archetypeが表示されるようになります。

Ubuntu16.04 に Node.js v6 をインストールする

UbuntuでPPAを使用してapt-get installする方法として、オフィシャルサイトでは次のコマンドを実行するように書かれています

curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs

しかし1行目を実行しても /etc/apt/sources.list.d/ にPPAは追加されませんし、そのため2行目を実行するとUbuntuオフィシャルリポジトリに登録されている v4.2.6 がインストールされてしまいます。

オフィシャルサイトの説明を読む限り、"Chris Lea's Launchpad PPA"を利用しているそうで、それはおそらくここのことでしょう。
https://launchpad.net/~chris-lea/+archive/ubuntu/node.js

…最終更新日結構古いし16.04(Xenial Xerus)向けのものが無いように見える…

というわけで、

を参考にして手動でソースリストを作成しました。以下手順です。

まず /etc/apt/sources.list.d/nodesource.list ファイルを作成し次の内容を書き込みます:

deb https://deb.nodesource.com/node_6.x xenial main
deb-src https://deb.nodesource.com/node_6.x xenial main

https://deb.nodesource.com/node_6.x/dists/xenial/main/ を参照するようになる、のでしょう。

続いて上記リポジトリの公開鍵を登録します:

curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add -

ローカルのリポジトリインデックスファイルを更新します:

sudo apt-get update

これで準備は整いました。インストールします:

sudo apt-get install nodejs

以上です。

GWT JsInterop を利用した AltJS としての Java

従来Javaで実装されていたGoogle Closure CompilerがJavaScript(Node.js module)で提供されるようになった、という話題が先日ありました。

上記のエントリのコメントを読むと、GWTで変換しているのだ、ということが書かれていて驚きました。

GWTGWTの中で完結させてしまうのが想定された用法であり、JavaScriptから呼び出したりはできないものだと思い込んでいたためです。

そこでリポジトリを覗いてみたところ、JsInterop機能が利用されていることに気付きました。
もうすぐリリースされるGWTバージョン2.8.0から正式機能として利用できるもの…ということは知っていたのですが、具体的に何をするのものなのかは考えたり調べたりしたことがありませんでした。

というわけで今回どんなものなのかハローワールドプログラムを作ってみました。

Javaで書いたクラスがこちら、これを呼び出しているJavaScriptこちらです。

gwt-maven-plugin で雛形を作って、あとはgitの履歴に有るとおりです。

JavaができるんならJavaScriptもいけるでしょ?」が現実になるわけですね…!