Cygwinでjarファイルを実行しようとしたらError: Unable to access jarfileとなった

Cygwinでjarファイルを実行しようとしたらGit Bashでは生じないエラーに見舞われた

% java -jar /cygdrive/c/jar/hoge.jar
Error: Unable to access jarfile /cygdrive/c/hoge.jar

ちゃんと指定したパスにファイルがあるはずなのにアクセスできないと言われる。

調べてみるとCygwinにおいてjavaWindows形式でパスを書かないといけないらしい

% java -jar c:/jar/hoge.jar

ってやったら上手くいった

ちなみに\(バックスラッシュ)でやろうとすると

% java -jar c:\\jar\\hoge.jar

このようにエスケープする必要があって非常に面倒くさい

Pythonのlambda(無名関数)について

lambdaって見た目からして難しそうですね、でも使えるこなせるようになってみたい

例えば引数を2乗する関数は普通に書くとこうなりますね

def foo(x):
    return x ** 2

print(foo(3))
# 9

lamdaを使うとこうなります

lam = lambda x: x ** 2

print(lam(3))
# 9

この場合ではfooとlamが等価になっていますね

つまり

lambda (引数): (戻り値)

で関数になるということです。

「関数になる」というのがよく分からない場合はPythonの対話型シェルを開いて次のコードを打ち込んでみると分かりやすい

>>> (lambda x: x ** 2)(3)
9

(lambda x: x ** 2)が普通の関数と同じように使えています。(3)が引数の部分ですね

次に条件分岐を加えてみます

print((lambda x: x ** 2 if x > 10 else 0)(3))
# 0

x >10ならばx ** 2を返しそうでなければ0を返すという意味です

これは条件演算子三項演算子と呼ばれ他にもいろいろな書き方がある

これを普通にやろうとすると

def foo(x):
    if x > 10:
        return x ** 2
    else:
        return 0

print(foo(3))

となってかなり面倒臭いです

1回しか使わないような細かい関数はdefしないでlamdaを使っていこう!

引数で関数を指定するときに使うことが多いらしいです

コードも見やすくなりそう

CygwinをExplorerのコンテキストメニュー(右クリック)から開く

ググれば似たような記事はわんさか出てくるけどメモ代わりとして

  1. Cygwinを管理者権限で開く
  2. chereが入っていなければapt-cyg install chereでインストール
  3. chere -ian -e "Cygwin" -t mintty -s zshと入力
    -eオプションでコンテキストメニューで出てくるメッセージを決められる。 -tで開くターミナル、-sで開くシェルを指定できる。bashでいい人は-sオプションはいらない。
    コンテキストメニューの表示を消したいときはchere -u、設定を上書きするときは-fオプション。

右クリックから開けるというだけでGit Bashを使っていたのですがこれでCygwinの利用頻度が上がりそうです。

EclipseでのMavenプロジェクトの作成、jarファイルの作り方

基本的なことだけど躓くところが多かったのでまとめてみた。

Mavenプロジェクト作成

NewからMaven Projectを選ぶ f:id:beback:20161118232539p:plain Create a simple projectにチェックを入れる
Group IdとArtifact Idを入力する
Artifact Idはプロジェクト名になるようだ

pom.xmlの編集

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
  <dependency>
    <groupId>org.twitter4j</groupId>
    <artifactId>twitter4j-core</artifactId>
    <version>[4.0,)</version>
  </dependency>
</dependencies>
<build>
<plugins>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
      <execution>
        <id>make-assembly</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive><manifest><mainClass>myclient.Main</mainClass></manifest></archive>
    </configuration>
  </plugin>
</plugins>
</build>

外部ライブラリとしてtwitter4jを使った時のものです。

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

これがないとダイヤモンド演算子が使えないなどといったエラーメッセージがでました。

<dependencies>
  <dependency>
    <groupId>org.twitter4j</groupId>
    <artifactId>twitter4j-core</artifactId>
    <version>[4.0,)</version>
  </dependency>
</dependencies>

これは依存するライブラリを指定しています。自動でダウンロードまでしてくれて便利!

<build>
<plugins>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
      <execution>
        <id>make-assembly</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive><manifest><mainClass>myclient.Main</mainClass></manifest></archive>
    </configuration>
  </plugin>
</plugins>
</build>

これを書くことでスタンンドアロンなjarファイルが作れました。
mainClassタグを書かないと「メイン・マニフェスト属性がありません」と怒られます。 パッケージ名.メインクラス名を指定してください。
(Windowでのjavashift_jisで出てくるので文字化けして最初は途方に暮れてしまいました。 文字化けしたらコマンドプロンプトなどのターミナルのフォントをshift_jisにしてあげましょう。)

jarファイル作成、実行

プロジェクトのコンテキストメニュー(右クリック)からRan as -> Maven build...をクリック f:id:beback:20161119000759p:plain Goalsにpackageと入力
f:id:beback:20161119000804p:plain

プロジェクトのtargetディレクトリにjarファイルが生成される。ターミナルから

java -jar hatena-0.0.1-SNAPSHOT-jar-with-dependencies.jar

とやれば実行できる。

文字化けについて補足

javaプログラムの出力をutf-8で出力させたいときは

PrintStream stdo = new PrintStream(System.out, true, "UTF-8");
stdo.println("utf-8で出力!");

みたいにしてやればよい

lsしたときの色を変える

デフォルトだと書き込み権限のあるディレクトリがすごく見づらかったので調べてみた。
/etc/DIR_COLORSをもとに設定ファイルを編集します。

cp /etc/DIR_COLORS ~/.dircolors
vim ~/.dircolors

これで画像にある数字の部分を編集していきます。
数字に対応する色はコメント部分に説明があります。
f:id:beback:20161117104102p:plain vimで~/.dircolorsを編集すると色を付けてくれるので非常にやりやすいです。

OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky

僕の場合はこれの'34;'を消しました。新しくシェルを起動させると自動的に適用されます。

メモ

/etc/DIR_COLORS.256colorというのもある。時間があるときに調べよう。

Pythonで大文字、小文字の区別をせずに文字列を検索

今まで正規表現を使って

p = re.compile(".*" + name + ".*", re.IGNORECASE)
res = p.match(string)
if res != None:
# 続きの処理

とやってたんですが

if name.lower() in string.lower():
# 続きの処理

てやれば簡単だね

Javaのジェネリクスとjsonファイルの作り方

Javaジェネリクス(総称型)はC++でいうテンプレートらしいです。
これを使えばjson用のオブジェクトも楽に作れそう

import java.util.ArrayList;
import java.util.List;

public class MyJson<T> {
    public int num;
    public List<T> extras;
    
    MyJson() {
        this.num = -1;
        this.extras = new ArrayList<>();
    }
}

これを使うときはこんな感じにやればいいかな? jsonへのエンコードjsonicを使っています。

public class MakeJson {
    public static void main(String[] args) {
        PrinterWriter out1 = new PrinterWriter(args[1]);
        PrinterWriter out2 = new PrinterWriter(args[2]);
        MyJson<String> obj1 = new MyJson<>();
        MyJson<Map<String, String>> obj2 = new MyJson<>();
        obj1.num = 1;
        List<String> extras1 = new ArrayList<>();
        obj1.extras = extras1;
        obj2.num = 2;
        Map<String, String> extras2 = new Map<>();
        obj2.extras = extras2;
        String string1 = JSON.encode(obj1, ou1, true);
        String string2 = JSON.encode(obj2, out2, true);
        out1.close();
        out2.close();
    }
}