SpringのStreamUtilsの紹介

1概要

この記事では、 StreamUtils クラスとその使用方法について説明します。

簡単に言うと、 StreamUtils はSpringのクラスで、ストリームを扱うためのユーティリティメソッドがいくつか含まれています。 InputStream OutputStream は、パッケージ java.io にあり、Java 8のStream APIとは関係ありません。

2 Mavenの依存関係

StreamUtils クラスはspring-coreモジュールにありますので、それを pom.xml に追加しましょう。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>

ライブラリの最新版はhttps://mvnrepository.com/artifact/org.springframework/spring-core[Maven Central Repository]にあります。

3ストリームのコピー

StreamUtils クラスには、 copy() という名前のオーバーロードメソッド、およびその他のバリエーションが含まれています。

  • copyRange()

  • copyToByteArray()

  • copyString()

ライブラリを使用せずにストリームをコピーできます。しかし、コードは面倒になり、読み、理解するのがはるかに難しくなります。

わかりやすくするため、ストリームのクローズは省略しています。

InputStream のコンテンツを特定の OutputStream にコピーする方法を見てみましょう。

@Test
public void whenCopyInputStreamToOutputStream__thenCorrect() throws IOException {
    String inputFileName = "src/test/resources/input.txt";
    String outputFileName = "src/test/resources/output.txt";
    File outputFile = new File(outputFileName);
    InputStream in = new FileInputStream(inputFileName);
    OutputStream out = new FileOutputStream(outputFile);

    StreamUtils.copy(in, out);

    assertTrue(outputFile.exists());
    String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
    String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));
    assertEquals(inputFileContent, outputFileContent);
}

作成されたファイルは InputStream の内容を含みます。

getStringFromInputStream() InputStream を受け取り、その内容を String として返すメソッドです。メソッドの実装は、コードのフルバージョンで利用可能です。

InputStream のコンテンツ全体をコピーする必要はありません。 copyRange() メソッドを使用して、特定の OutputStream にコンテンツの範囲をコピーできます。

@Test
public void whenCopyRangeOfInputStreamToOutputStream__thenCorrect() throws IOException {
    String inputFileName = "src/test/resources/input.txt";
    String outputFileName = "src/test/resources/output.txt";
    File outputFile = new File(outputFileName);
    InputStream in = new FileInputStream(inputFileName);
    OutputStream out = new FileOutputStream(outputFileName);

    StreamUtils.copyRange(in, out, 1, 10);

    assertTrue(outputFile.exists());
    String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
    String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));

    assertEquals(inputFileContent.substring(1, 11), outputFileContent);
}

ここでわかるように、 copyRange() は4つのパラメーター、 InputStream OutputStream 、コピーを開始する位置、およびコピーを終了する位置を取ります。しかし、指定された範囲が InputStream の長さを超えるとどうなりますか?メソッド copyRange() は、ストリームの最後までコピーします。

String の内容を特定の OutputStream にコピーする方法を見てみましょう。

@Test
public void whenCopyStringToOutputStream__thenCorrect() throws IOException {
    String string = "Should be copied to OutputStream.";
    String outputFileName = "src/test/resources/output.txt";
    File outputFile = new File(outputFileName);
    OutputStream out = new FileOutputStream("src/test/resources/output.txt");

    StreamUtils.copy(string, StandardCharsets.UTF__8, out);

    assertTrue(outputFile.exists());

    String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));

    assertEquals(outputFileContent, string);
}

メソッド copy() は3つのパラメータを取ります - コピーされる String 、ファイルに書き込むために使用したい Charset 、そして String の内容をコピーしたい OutputStream

与えられた InputStream の内容を新しい String にコピーする方法は次のとおりです。

@Test
public void whenCopyInputStreamToString__thenCorrect() throws IOException {
    String inputFileName = "src/test/resources/input.txt";
    InputStream is = new FileInputStream(inputFileName);
    String content = StreamUtils.copyToString(is, StandardCharsets.UTF__8);

    String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
    assertEquals(inputFileContent, content);
}

与えられたバイト配列の内容を OutputStream にコピーすることもできます。

public void whenCopyByteArrayToOutputStream__thenCorrect() throws IOException {
    String outputFileName = "src/test/resources/output.txt";
    String string = "Should be copied to OutputStream.";
    byte[]byteArray = string.getBytes();
    OutputStream out = new FileOutputStream("src/test/resources/output.txt");

    StreamUtils.copy(byteArray, out);

    String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));

    assertEquals(outputFileContent, string);
}

あるいは、与えられた InputStream の内容を新しいバイト配列にコピーすることもできます。

public void whenCopyInputStreamToByteArray__thenCorrect() throws IOException {
    String inputFileName = "src/test/resources/input.txt";
    InputStream is = new FileInputStream(inputFileName);
    byte[]out = StreamUtils.copyToByteArray(is);

    String content = new String(out);
    String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));

    assertEquals(inputFileContent, content);
}

4その他の機能

InputStream を引数としてメソッド drain() に渡すことで、ストリーム内の残りのすべてのデータを削除できます。

StreamUtils.drain(in);

メソッド emptyInput() を使って効率的な空の InputStream を取得することもできます。

public InputStream getInputStream() {
    return StreamUtils.emptyInput();
}

nonClosing() という名前の2つのオーバーロードメソッドがあります。 InputStream または OutputStream をこれらのメソッドに引数として渡して、 close() メソッドの呼び出しを無視する InputStream または OutputStream のバリアントを取得できます。

public InputStream getNonClosingInputStream() throws IOException {
    InputStream in = new FileInputStream("src/test/resources/input.txt");
    return StreamUtils.nonClosing(in);
}

5結論

このクイックチュートリアルでは、 StreamUtils が何であるかを見てきました。また、 StreamUtils クラスのすべてのメソッドについても説明しました。これらのメソッドの使用方法を確認しました。

このチュートリアルの完全な実装はhttps://github.com/eugenp/tutorials/tree/master/spring-core[over on GitHub]にあります。