2016/07/21

LHA Library for javaをC#から使う

jLHA(LHA Library for Java)は、LHA書庫を扱えるJavaのライブラリです。素晴らしい!
でも、.NETで使えないものか?

使えるのです。
IKVM.NETは、.NET Framework上で動作するJava VMです。このプロダクトの一つに、Javaのjarファイルを.NETのEXEまたはDLLに変換してくれるikvmcがあります。
まずは、LHA Library for Javaをjarにします。サイトで配布しているのは、Javaのソースなので、Eclipseでソース一式を読み込ませて、Exportでjarファイルを作成します。
そのjarファイルをIKVM.NETサイトからダウンロードしたikvmbin-7.2.4630.5.zipを展開したディレクトリ配下のbinディレクトリにコピーします。
コマンド プロンプトを開き、先ほどのbinディレクトリに移動します。

C:\Users\heropa\ikvmbin-7.2.4630.5\bin>ikvmc -target:library -platform:anycpu jlha-lib.jar
IKVM.NET Compiler version 7.2.4630.5
Copyright (C) 2002-2012 Jeroen Frijters
http://www.ikvm.net/

note IKVMC0002: Output file is "jlha-lib.dll"

これで、.NETで使用できるDLLが作成されます。
.NETでの参照設定には、上記DLLとIKVM.OpenJDK.Core.dllを加えます。
C#のソースは、こんな感じ。

using jp.gr.java_conf.dangan.util.lha;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jlha_lib_test
{
    class Program
    {
        static void Main(string[] args)
        {
            LhaFile lha = new LhaFile("C:\\Users\\heropa\\Downloads\\cldx\\jack020.lzh");
            LhaHeader[] headers = lha.getEntries();
            foreach(LhaHeader h in headers)
            {
                Console.WriteLine("Path:{0}", h.getPath());
                Console.WriteLine("CompressedSize:{0}", h.getCompressedSize());
                Console.WriteLine("OriginalSize:{0}", h.getOriginalSize());
                Console.WriteLine("LastModified:{0}", javadateToString(h.getLastModified()));
                Console.WriteLine("Method:{0}", h.getCompressMethod());
                Console.WriteLine("CRC:{0:X}", h.getCRC());
                Console.WriteLine("----------");
            }
            Console.ReadKey();
        }

        private static string javadateToString(java.util.Date javaDate)
        {
            DateTime date = new DateTime(javaDate.getYear() + 1900,
                                         javaDate.getMonth() + 1,
                                         javaDate.getDate(),
                                         javaDate.getHours(),
                                         javaDate.getMinutes(),
                                         javaDate.getSeconds());


            return date.ToLongDateString() + " " + date.ToLongTimeString();
        }
    }
}

Javaのクラスが所々混じって変な感じです。
getLastModifiedメソッドが返すjava.util.Dateは、年が1900年ほど足りないようです...。
java.util.Date.getMonthメソッドは、0始まりなので、DateTimeとは、1ズレるんですよね、javaってなんでこんな仕様なんだろう?って思うことがしばしば...。
出力は、こんな感じ。

Path:Jack32.dll
CompressedSize:37473
OriginalSize:75264
LastModified:2002年06月01日 18:08:04
Method:-lh5-
CRC:AE67
----------
Path:Jack32.lib
CompressedSize:1079
OriginalSize:4986
LastModified:2002年06月01日 18:08:02
Method:-lh5-
CRC:2BA1
----------
Path:JackApi.h
CompressedSize:5320
OriginalSize:19339
LastModified:2001年11月02日 21:42:08
Method:-lh5-
CRC:88AB
----------
Path:Api.txt
CompressedSize:2959
OriginalSize:11284
LastModified:2002年06月01日 18:05:48
Method:-lh5-
CRC:429E
----------
Path:Command.txt
CompressedSize:2058
OriginalSize:5789
LastModified:2002年06月01日 18:05:52
Method:-lh5-
CRC:D4AE
----------
Path:Jack32.txt
CompressedSize:4282
OriginalSize:10277
LastModified:2002年06月01日 18:07:06
Method:-lh5-
CRC:B231
----------

わざわざこんな事をしなくても、WindowsにはUnLHA32.DLLがあるじゃないか!
ごもっともです。
ただ、IKVM経由でjLHAを使うってことは、64bit版アプリを簡単に作れるってことなんですよね?!
暑いから試してないけど。
(^_^;)

2016/07/02

車輪の再発明について思ったこと

プログラマにとって、車輪の再発明は駄目なことではないし、無駄でもない。
けど、その車輪が使えるものなら、使わないと損だよね。

車輪(ライブラリとかソリューション)の再発明をしてしまう理由とは、
  1. 車輪を自分で作りたかったから。
  2. その車輪の存在を知らなかった。
  3. その車輪に欠陥が多くて使えないから。
  4. ライセンスで使えないから。
順番には意図は無いです。
1. と3. はどんどんやるべきだと思う。2. は、できるだけ避けたい。そのためには、事前の技術調査が必要なんだと思う。
4. なんだけど、再利用が制限されるライセンスって困る。個人的には、MITライセンス的なものが嬉しい。

車輪の再発明が悪でないと思うのは、多様性がある方が色々いいんじゃないかと思うんですよ。
例えば、なんたらFileUploadの脆弱性で、そのライブラリを使っているプロダクトが軒並み脆弱性の影響を受ける、とか...。
H・G・ウェルズの宇宙戦争の火星人のよう。