MarkLogic アプリ開発チュートリアル：バイナリファイルの読み書き

NoSQL製品であるMarkLogicのチュートリアル第３回です。

バイナリファイルを読み書きするサンプルを作ってみます。

以下の手順を既に済ませている前提で説明します。

* [MarkLogicのユーザーの作成](http://qiita.com/makopo/items/0d024b827880111f8a8f#marklogicのユーザーの作成)
* [Javaプロジェクトの作成](http://qiita.com/makopo/items/0d024b827880111f8a8f#javaプロジェクトの作成)
* [Java APIライブラリのダウンロード](http://qiita.com/makopo/items/0d024b827880111f8a8f#marklogic-java-apiライブラリのダウンロード)

## 準備

プロジェクトのルートディレクトリに```my.png```という名称でバイナリファイルを置きます。

## データベースに書き込むクラスの作成

```java:WriteBinaryData.java
    public static void main(String[] args) {
        // データベースクライアントの取得
        DatabaseClient client = DatabaseClientFactory.newClient(
                "localhost", 8000, "aaa", "pass", DatabaseClientFactory.Authentication.DIGEST
        );

        // DocumentManagerの取得
        BinaryDocumentManager biMgr = client.newBinaryDocumentManager();

        // データベースにメタデータも書き込まれるように指定
        // (指定が無い場合、書き込まれない)
        biMgr.setMetadataExtraction(BinaryDocumentManager.MetadataExtraction.PROPERTIES);

        // バイナリデータを書き込み
        biMgr.write(
                "/example/my.png",
                new FileHandle().with(new File("my.png")).withMimetype("image/png")
        );

        // クライアントの解放
        client.release();

    }
```

* ```BinaryDocumentManager```を使います。
* このサンプルでは```FileHandle```を使っていますが、以下のHandleのどれを使っても良いです。
    * ```FileHandle```
    * ```BytesHandle```
    * ```InputStreamHandle```
    * ```OutputStreamHandle```
    * ```URIHandle```

### 実行

ビルドして実行します。

```shell-session
19:47:01.551 [main] DEBUG c.m.client.DatabaseClientFactory - Creating new database client for server at localhost:8000
19:47:01.576 [main] DEBUG c.m.client.impl.JerseyServices - Connecting to localhost at 8000 as aaa
19:47:01.854 [main] INFO  c.m.client.impl.DocumentManagerImpl - Writing content for /example/my.png
19:47:01.855 [main] DEBUG c.m.client.impl.JerseyServices - Sending /example/my.png document in transaction null
19:47:03.121 [main] INFO  c.m.client.impl.DatabaseClientImpl - Releasing connection
19:47:03.121 [main] DEBUG c.m.client.impl.JerseyServices - Releasing connection
```

クエリコンソールで確認します。http://localhost:8000/qconsole/
![png.png](https://qiita-image-store.s3.amazonaws.com/0/10290/a6970e50-bd51-12c2-00a3-a44594e4432d.png)

リンクをクリックすると、アップロードした画像が表示されます。

## データベースから読み込むクラスの作成

```java:ReadBinaryData.java
    public static void main(String[] args) {

        // データベースクライアントの取得
        DatabaseClient client = DatabaseClientFactory.newClient(
                "localhost", 8000, "aaa", "pass", DatabaseClientFactory.Authentication.DIGEST
        );

        // DocumentManagerの取得
        BinaryDocumentManager biMgr = client.newBinaryDocumentManager();

        // ストリームに読み込む
        InputStream is =
                biMgr.read("/example/my.png", new InputStreamHandle()).get();

        // ローカルファイルのストリームを開く
        try (FileOutputStream fos = new FileOutputStream("/tmp/my.png")) {
            // 読み込んだ内容を転記
            ReadableByteChannel rbc = Channels.newChannel(is);
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);

        } catch (IOException e) {
            // エラーが発生したら中断
            throw new RuntimeException(e);

        } finally {
            // クライアントの解放
            client.release();
        }

    }
```

* ```BinaryDocumentManager```を使います。
* このサンプルでは```InputStreamHandle```を使っていますが、書き込みの場合と同様、他も使えます。

### 実行

ビルドして実行します。

```shell-session
19:50:15.740 [main] DEBUG c.m.client.DatabaseClientFactory - Creating new database client for server at localhost:8000
19:50:15.761 [main] DEBUG c.m.client.impl.JerseyServices - Connecting to localhost at 8000 as aaa
19:50:16.065 [main] INFO  c.m.client.impl.DocumentManagerImpl - Reading metadata and content for /example/my.png
19:50:16.066 [main] DEBUG c.m.client.impl.JerseyServices - Getting /example/my.png in transaction null
19:50:16.642 [main] INFO  c.m.client.impl.DatabaseClientImpl - Releasing connection
19:50:16.642 [main] DEBUG c.m.client.impl.JerseyServices - Releasing connection
```

先ほどデータベースにアップロードしたファイルと同じ内容のファイルが、```/tmp/my.png```に作成されているはずです。