0

我非常了解 Java 库,所以当我意识到显然没有简单的方法可以用流做一些看似简单的事情时,我感到很惊讶。我正在尝试读取包含多部分表单数据的 HTTP 请求(大的多行标记分隔为看起来像的分隔符,例如,------WebKitFormBoundary5GlahTkFmhDfanAn--),并且我想读取直到遇到具有给定名称的请求的一部分,然后返回该部分的 InputStream。

我可以将流读入内存并返回 a ByteArrayInputStream,因为提交的文件不应大于 1MB。但是,我想确保如果文件大于 1MB,读取方法会引发异常,以便过大的文件不会填满 JVM 的内存并导致服务器崩溃。文件数据可能是二进制的,因此排除BufferedReader.readLine()(它会删除换行符,可能是 、 或 中的任何一个\r\n导致\r\n数据丢失)。

所有明显的标记化解决方案,例如Scanner,将标记读取为Strings,而不是流,这可能导致OutOfMemoryErrors 用于大文件——这正是我想要避免的。据我所知,没有任何等价物Scanner将每个令牌作为 an 返回InputStream而不将其读入内存。是否有我遗漏的东西,或者有什么方法可以自己创建类似的东西,只使用标准 Java 库(没有Apache Commons 等),不需要我一次读取流一个字符并自己编写所有令牌扫描代码?


附录:在发布此之前不久,我意识到我最初的问题的明显解决方案是将完整的请求正文读入内存,如果它太大则失败,然后ByteArrayInputStreamScanner. 这是低效的,但它有效。但是,我仍然很想知道是否有一种方法可以将 a 标记InputStream为子流,无需将它们读入内存,无需使用额外的库,也无需采用逐个字符的处理。

4

1 回答 1

0

如果不将它们加载到内存(您不想要的解决方案)或将它们保存到磁盘(变得 I/O 繁重),这是不可能的。将流标记为单独的流而不将其加载到内存中意味着您可以读取流(对其进行标记)并能够稍后再次读取它。简而言之,除非您的流是可搜索的,否则您想要什么是不可能的,但这些通常是用于非常特定的应用程序和专用 I/O 对象的专用流,例如RandomAccessFile.

于 2013-07-10T02:03:50.137 回答