避免多次获得相同的InputStream



我可以看到有一些关于重用InputStream的帖子。我知道InputStream是一次性的,不能重复使用。

然而,我有一个这样的用例:

我通过DropBox's Java SDK获取DropBoxInputStreamDropBox下载了文件。然后,我需要通过传递InputStream将文件上传到另一个系统。但是,作为下载的一部分,我必须提供文件的MD5。所以我必须在上传文件之前从流中读取文件。因为我收到的DropBoxInputStream只能使用一次,所以我必须在计算完MD5之后,在上传文件之前再获得一个DropBoxInputStream。过程如下:

  1. 获取第一个DropBoxInputStream
  2. 从DropBoxInputStream中读取并计算MD5
  3. 获取第二个DropBoxInputStream
  4. 使用MD5和第二个DropBoxInputStream上传文件。

我在想,在我计算MD5之前,如果有很多方法可以让我"缓存"或"备份"InputStream,以便我可以再次保存获得相同DropBoxInputStream的步骤3 ?

多谢编辑:

对不起,我错过了一些信息。

我目前正在做的是我使用MD5DigestOutputStream来计算MD5。我通过MD5DigestOutputStream流数据并将它们保存为本地临时文件。一旦数据通过MD5DigestOutputStream,它将计算MD5

然后我调用第三方库来上传文件,使用计算的md5和从临时文件读取的FileInputStream

然而,这有时需要巨大的磁盘空间,我想删除使用临时文件的需要。我使用的库只接受MD5InputStream。这意味着我必须在我的端计算MD5。我的计划是使用我的MD5DigestOutputStream将数据写入/dev/null(不保留文件),以便我可以计算MD5,并再次从DropBox获得InputStream并将其传递给我使用的库。我假设库将能够直接从DropBox获取文件,而不需要我在内存或磁盘上缓存文件。它会起作用吗?

输入流并不是真正为创建副本或重用而设计的,它们专门用于您不想读入字节数组并对其使用数组操作的情况(这在整个数组不可用时特别有用,例如套接字通信)。你可以把数据缓存到字节数组中,这是将数据流中的部分读入字节数组缓冲区的过程,直到你有足够的信息。

但是这对于计算md5是不必要的。注意,InputStream是抽象的,因此需要在扩展类中实现。它有许多实现- GZIPInputStream, fileinputstream等。用设计模式的话说,它们是IO流的装饰器:它们为抽象的IO基类添加了额外的功能。例如,GZIPInputStream gzip up up .

所以,你需要的是一个流来完成md5。令人高兴的是,有一件类似的事情被很好地记录了下来:看看这个答案。所以你应该只是能够传递你的dropbox输入流(因为它本身就是一个输入流)来创建一个新的DigestInputStream,然后你都可以采取md5并继续像以前一样读取。

担心类型转换吗?Java中装饰器的想法是,因为InputStream 基类接口了你需要做IO的所有方法和"beef",所以在每个流实现的构造函数中传递从InputStream继承的对象实例没有害处,你仍然可以做相同的核心IO。最后,我可能应该回答你的实际问题——假设你仍然想要"缓存"或"备份"流?你可以把它写进字节数组。这是有据可查的,但当您的流变得更复杂时,可能会变得很麻烦。或者,尝试查看PushbackInputStream。在这里,您可以轻松地编写一个函数来读取n个字节,对它们执行和操作,然后将它们恢复到流中。一般来说,最好在Java中避免这些流的实现,因为它不利于内存使用,但并不比缓冲所有你必须做的事情更糟糕。

或者,当然,我会用DigestInputStream

希望有帮助,

你不需要从DropBox打开一个新的InputStream。

一旦你从DropBox读取了文件,你就在本地拥有了它。所以它要么在内存中(在字节数组中),要么存储在本地文件中。现在,您可以创建一个InputStream,从内存(ByteArrayInputStream)或磁盘(FileInputStream)读取数据,以便上传文件。

所以不是缓存InputStream(你不能),而是缓存内容(你可以)。

相关内容

  • 没有找到相关文章

最新更新