1. ホーム
  2. java

[解決済み] InputStreamをクローンする方法は?

2022-04-15 13:53:51

質問

あるメソッドに渡すInputStreamがあり、何らかの処理を行っています。同じInputStreamを他のメソッドで使用しますが、最初の処理の後、InputStreamはメソッド内でクローズされるようです。

InputStreamをクローンして、クローズしたメソッドに送るにはどうしたらよいでしょうか?他の解決策がありますか?

EDIT: InputStreamをクローズするメソッドは、ライブラリの外部メソッドです。私は閉じるかどうかを制御することはできません。

private String getContent(HttpURLConnection con) {
    InputStream content = null;
    String charset = "";
    try {
        content = con.getInputStream();
        CloseShieldInputStream csContent = new CloseShieldInputStream(content);
        charset = getCharset(csContent);            
        return  IOUtils.toString(content,charset);
    } catch (Exception e) {
        System.out.println("Error downloading page: " + e);
        return null;
    }
}

private String getCharset(InputStream content) {
    try {
        Source parser = new Source(content);
        return parser.getEncoding();
    } catch (Exception e) {
        System.out.println("Error determining charset: " + e);
        return "UTF-8";
    }
}

解決方法は?

同じ情報を複数回読み込むだけで、入力データがメモリに収まるほど小さい場合は、データを自分の InputStream を追加しました。 バイトアレイアウトプットストリーム .

そして、関連するバイトの配列を取得し、多くの "clone" を開くことができます。 バイトアレイインプットストリーム を好きなだけ使うことができます。

ByteArrayOutputStream baos = new ByteArrayOutputStream();

// Code simulating the copy
// You could alternatively use NIO
// And please, unlike me, do something about the Exceptions :D
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) > -1 ) {
    baos.write(buffer, 0, len);
}
baos.flush();
    
// Open new InputStreams using recorded bytes
// Can be repeated as many times as you wish
InputStream is1 = new ByteArrayInputStream(baos.toByteArray()); 
InputStream is2 = new ByteArrayInputStream(baos.toByteArray()); 

しかし、新しいデータを受け取るためにオリジナルのストリームを開いておく必要が本当にあるのなら、外部呼び出しの close() . を防ぐ必要があります。 close() が何らかの方法で呼び出されないようにします。

UPDATE(2019年)。

Java 9以降では、中間ビットを InputStream.transferTo :

ByteArrayOutputStream baos = new ByteArrayOutputStream();
input.transferTo(baos);
InputStream firstClone = new ByteArrayInputStream(baos.toByteArray()); 
InputStream secondClone = new ByteArrayInputStream(baos.toByteArray());