猿问

BufferedReader 如何从 S3 读取文件?

我在 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 逐行读取?或者介于两者之间?


弑天下
浏览 173回答 3
3回答

跃然一笑

您链接的文档中已经给出了您问题的答案之一:在您读取所有数据或关闭输入流之前,您的网络连接将保持打开状态。ABufferedReader不知道它读取的数据来自哪里,因为您正在将另一个数据传递Reader给它。ABufferedReader创建一个特定大小的缓冲区(例如 4096 个字符),并Reader在开始分发read()or调用的数据之前通过从底层读取来填充该缓冲区read(char[] buf)。在Reader您传递到BufferedReader是-顺便说一句-用另一个缓冲区为自己做从转换byte基于流为char基础的读者。它的工作方式与 with 相同BufferedReader,因此内部缓冲区是通过从S3 客户端返回的传递InputStream中读取来填充的InputStream。如果您尝试从流中加载数据,那么在此客户端中究竟发生了什么取决于实现。一种方法是保持打开一个网络连接,您可以根据需要从中读取数据,或者可以在读取一大块数据后关闭网络连接,并在您尝试获取下一个数据时打开一个新连接。上面引用的文档似乎说我们在这里遇到了前一种情况,所以:不,调用readLine不会导致单个网络调用。并回答您的另一个问题:不, a BufferedReader,InputStreamReader并且很可能InputStream由 S3 客户端返回的 未将整个文档加载到内存中。这将与首先使用流的整个目的相矛盾,S3 客户端可以简单地返回 a byte[][](以达到每个byte数组2^32 字节的限制)编辑:最后一段有一个例外。如果整个千兆字节的大文档没有换行符,调用readLine实际上会导致将整个数据读入内存(最有可能是 OutOfMemoryError)。在回答您的问题时,我假设了一个“常规”文本文档。

慕哥9229398

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

相关分类

Java
我要回答