1

ImageIO.read()メソッドで奇妙な動作が見られます。

InputStreamをこのメソッドに渡しますが、2回目に読み取ろうとすると、読み取りに失敗してnullを返します。

Amazon S3に画像をアップロードしようとしていますが、画像の3つのバージョンを作成したいと思います。オリジナルと2つのサムネイル。私の問題は、2つのサムネイルを作成するときに、ImageIO.read()を使用してInputStreamを読み取る必要があることです。同じInputStreamに対してこのメ​​ソッド2を実行すると、2回目の読み取りでnullが発生します。

この問題を回避するには、1つだけを読み取り、同じBufferedImageをスケーリングメソッドに渡します。ただし、元のファイルをアップロードするために、メソッドが他のAmazonS3サービスに渡すInputStreamが必要です。

だから私の質問は、ImageIOが初めて入力ストリームを読み取った後、入力ストリームがどうなるかを誰かが知っているかどうかです。

以下のコードサンプル

public String uploadImage(InputStream stream, String filePath, String fileName, String fileExtension) {
    try {

        String originalKey = filePath + fileName + "." + fileExtension;
        String smallThumbKey = filePath + fileName + ImageConst.Path.SMALL_THUMB + "." + fileExtension;
        String largetThumbKey = filePath + fileName + ImageConst.Path.LARGE_THUMB + "." + fileExtension;

        BufferedImage image = ImageIO.read(stream); 
        InputStream smallThumb = createSmallThumb(image, fileExtension);
        InputStream largeThumb = createLargeThumb(image, fileExtension);

        uploadFileToS3(originalKey, stream);
        uploadFileToS3(smallThumbKey, smallThumb);
        uploadFileToS3(largetThumbKey, largeThumb);

        return originalKey;

    } catch (IOException ex) {
        Logger.getLogger(ManageUser.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}
4

2 に答える 2

1

ImageIO.read は、入力ストリームの最後まで読み取ります。つまり、読み取るデータが残っていないため、さらにデータを読み取ろうとすると null が返されます。

入力ストリームを再利用したい場合は、reset() を呼び出す必要があります。ただし、これは、基になる InputStream 実装がリセットをサポートしている場合にのみ機能します。InputStream の markSupported() を参照してください。

これは単純ですが、素朴な修正です。

すでにイメージをメモリに読み込んでいるので、実際にそれを行う必要はないことに注意してください。これは少し不器用ですが、これを ByteArrayOutputStream に書き出すことができ、それから新しい ByteArrayInputStream を構築できます。

これを行う場合、おそらく最初からバイト配列に読み込むでしょう。そのために Commons IOUtils.read() をチェックしてください。次に、新しい ByteArrayInputStream と reset() を作成します。これは、マーキングを確実にサポートするためです。

于 2012-11-14T22:36:29.470 に答える
0

元の入力ストリームをBufferedInputStreamでラップし、mark()を使用してストリーム内の開始位置を保存し、reset()を使用してそれに戻ることができると思います。

あなたの質問に完全に答えるには:すべてのストリームが順番に読み取られます(多くの場合、現在の位置を指す何らかの内部ポインターがあります)。最初の の後ImageIO.read()、ストリームは最後まで読み取られるため、それ以降の読み取り操作ではデータが返されません (通常、ストリームの末尾を示す -1)。mark() を使用すると、特定の位置を保存し、後で reset() を使用してその位置に戻ることができます。

于 2012-11-14T22:25:33.390 に答える