InputStream為什么不能被重復讀取?


最近上傳阿里雲的時候同一個文件上傳兩個服務地址,第一個文件讀取以后第二個再去讀取就拿不到了。代碼如下:

   //內網上傳OSS獲取key值
        String ossKey = OSSClientUtil.getOSSURL(endpoint, accessKeyId, accessKeySecret, bucketName, key, inputStream);
        //外網上傳OSS獲取key值
        String outOssLink = OSSClientUtil.getOutOSSLink(outEndpoint, outAccessKeyId, outAccessKeySecret, outBucketName, key,
                inputStream); 

導致第二次上傳失敗。

Java中的Inputstream是不能重復讀取的。
但是有沒有想過,InputStream為什么不能重復讀呢?
其實要回答“為什么”這個問題很簡單,就是人家接口就是這么設計的,不能重復讀。
所以今天要討論的問題更像是:Java的InputStream為什么要設計為不能重復讀?
關於InputStream為什么不能重復讀取,網上也各有說法:
有的同學說:
“InputStream就類比成一個杯子,杯子里的水就像InputStream里的數據,你把杯子里的水拿出來了,杯子的水就沒有了,InputStream也是同樣的道理。”
比喻的非常好,讓我們從直觀上認識了InputStream為什么不能重復被讀。
也有的同學從更深的代碼角度去分析:
“在InputStream讀取的時候,會有一個pos指針,他指示每次讀取之后下一次要讀取的起始位置,當讀到最后一個字符的時候,pos指針不會重置。”
說的也有道理,就是說InputStream的讀取是單向的。但是並不是所有的InputStream實現類都是這樣的實現方式。

Java 的List內部是使用數組實現的,遍歷的時候也有一個pos指針。但是沒有說List遍歷一個第二次遍歷就沒有了。第二次遍歷是創建新的Iterator,所以pos也回到了數組起始位置。對於某些InputStream當然可以也這么做。例如:ByteArrayInputStream
ByteArrayInputStream就是將一個Java的byte數組保存到對象里,然后讀取的時候遍歷該byte數組。

更改以后的代碼如下:

public class InputStreamFactory {

    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    private byte[]                buffer                = new byte[1024];

    public InputStreamFactory(InputStream input) throws IOException {
        int len;
        while ((len = input.read(buffer)) > -1) {
            byteArrayOutputStream.write(buffer, 0, len);
        }
        byteArrayOutputStream.flush();
    }

    public InputStream newInputStream() {
        return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    }

}

更改代碼:

  InputStreamFactory inputStreamFactory = null;
        try {
            inputStreamFactory = new InputStreamFactory(inputStream);
            //內網上傳OSS獲取key值
            String ossKey = OSSClientUtil.getOSSURL(endpoint, accessKeyId, accessKeySecret, bucketName, key,
                    inputStreamFactory.newInputStream());
            //外網上傳OSS獲取key值
            String outOssLink = OSSClientUtil.getOutOSSLink(outEndpoint, outAccessKeyId, outAccessKeySecret, outBucketName,
                    key, inputStreamFactory.newInputStream());
        } catch (IOException e) {
            log.info("讀取文件流失敗", e);
        }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM