为了账号安全,请及时绑定邮箱和手机立即绑定

BufferedReader 如何从 S3 读取文件?

BufferedReader 如何从 S3 读取文件?

弑天下 2021-06-08 15:06:45
我在 AWS S3 中有一个非常大的文件(几 GB),我只需要文件中满足特定条件的少量行。我不想将整个文件加载到内存中,然后搜索并打印那几行 - 这会导致内存负载太高。正确的方法是只加载内存中需要的那些行。根据从文件读取的AWS 文档:fullObject = s3Client.getObject(new GetObjectRequest(bucketName, key)); displayTextInputStream(fullObject.getObjectContent());private static void displayTextInputStream(InputStream input) throws IOException {    // Read the text input stream one line at a time and display each line.    BufferedReader reader = new BufferedReader(new InputStreamReader(input));    String line = null;    while ((line = reader.readLine()) != null) {        System.out.println(line);    }    System.out.println();}这里我们使用的是BufferedReader。我不清楚这里下面发生了什么。我们是否在每次读取新行时都对 S3 进行网络调用,并且只将当前行保留在缓冲区中?还是将整个文件加载到内存中,然后由 BufferedReader 逐行读取?或者介于两者之间?
查看完整描述

3 回答

?
跃然一笑

TA贡献1826条经验 获得超6个赞

您链接的文档中已经给出了您问题的答案之一:

在您读取所有数据或关闭输入流之前,您的网络连接将保持打开状态。

ABufferedReader不知道它读取的数据来自哪里,因为您正在将另一个数据传递Reader给它。ABufferedReader创建一个特定大小的缓冲区(例如 4096 个字符),并Reader在开始分发read()or调用的数据之前通过从底层读取来填充该缓冲区read(char[] buf)

Reader您传递到BufferedReader是-顺便说一句-用另一个缓冲区为自己做从转换byte基于流为char基础的读者。它的工作方式与 with 相同BufferedReader,因此内部缓冲区是通过从S3 客户端返回的传递InputStream中读取来填充的InputStream

如果您尝试从流中加载数据,那么在此客户端中究竟发生了什么取决于实现。一种方法是保持打开一个网络连接,您可以根据需要从中读取数据,或者可以在读取一大块数据后关闭网络连接,并在您尝试获取下一个数据时打开一个新连接。

上面引用的文档似乎说我们在这里遇到了前一种情况,所以:不,调用readLine不会导致单个网络调用。

并回答您的另一个问题:不, a BufferedReaderInputStreamReader并且很可能InputStream由 S3 客户端返回的 未将整个文档加载到内存中。这将与首先使用流的整个目的相矛盾,S3 客户端可以简单地返回 a byte[][](以达到每个byte数组2^32 字节的限制)

编辑:最后一段有一个例外。如果整个千兆字节的大文档没有换行符,调用readLine实际上会导致将整个数据读入内存(最有可能是 OutOfMemoryError)。在回答您的问题时,我假设了一个“常规”文本文档。


查看完整回答
反对 回复 2021-06-10
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

如果您基本上不是在搜索特定的单词/单词,并且您知道字节范围,则还可以在 S3 中使用 Range 标头。这应该特别有用,因为您正在处理几个 GB 大小的单个文件。指定范围不仅有助于减少内存,而且速度更快,因为只读取文件的指定部分。

查看完整回答
反对 回复 2021-06-10
  • 3 回答
  • 0 关注
  • 172 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信