BufferedReader 如何从 S3 读取文件?
How does BufferedReader read files from S3?
我在 AWS S3 中有一个非常大的文件(几 GB),我只需要文件中满足特定条件的少量行。我不想将整个文件加载到内存中,然后搜索并打印那几行——这样做的内存负载会太高。正确的方法是只加载内存中需要的那些行。
根据 AWS 文档to read from file:
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 逐行读取?还是介于两者之间?
取决于文件中行的大小。 readLine() 将继续构建字符串,以缓冲区大小的块为单位从流中获取数据,直到您遇到行终止符。所以使用的内存将是你的行长+缓冲区长度的顺序。
您链接的文档中已经给出了您问题的其中一个答案:
Your network connection remains open until you read all of the data or close the input stream.
A BufferedReader
不知道它读取的数据来自哪里,因为您正在将另一个 Reader
传递给它。 BufferedReader
创建一个特定大小的缓冲区(例如 4096 个字符),并在开始分发 read()
或 [=15 的调用数据之前通过从底层 Reader
读取来填充此缓冲区=].
你传递给 BufferedReader
的 Reader
是 - 顺便说一句 - 使用另一个缓冲区来完成从基于 byte
的流到 char
基reader。它的工作方式与 BufferedReader
相同,因此内部缓冲区通过读取传递的 InputStream
来填充,这是由您的 S3 客户端编辑的 InputStream
return。
如果您尝试从流中加载数据,此客户端中究竟发生了什么取决于实现。一种方法是保持打开一个网络连接,您可以根据需要从中读取,或者可以在读取一大块数据后关闭网络连接,并在您尝试获取下一个数据时打开一个新连接。
上面引用的文档似乎说我们这里有前一种情况,所以:不,readLine
的调用不会导致单个网络调用。
并回答您的其他问题:不,BufferedReader
、InputStreamReader
和很可能由 S3 客户端编辑的 InputStream
return 没有加载将整个文件存入内存。这将与首先使用流的整个目的相矛盾,S3 客户端可以简单地 return 一个 byte[][]
来代替(绕过每个 byte
数组 2^32 字节的限制)
编辑:最后一段有一个例外。如果整个千兆字节的大文档没有换行符,调用 readLine
实际上会导致将整个数据读入内存(并且很可能导致 OutOfMemoryError)。我在回答您的问题时假设了一个 "regular" 文本文档。
如果您基本上不是在搜索特定的 word/words,并且知道字节范围,您也可以在 S3 中使用范围 header。当您处理一个几 GB 大小的文件时,这应该特别有用。指定 Range 不仅有助于减少内存,而且速度更快,因为只读取文件的指定部分。
见Is there "S3 range read function" that allows to read assigned byte range from AWS-S3 file?
希望对您有所帮助。
Sreram
只对 AWS 基础设施进行一次 HTTP 调用,数据以小块的形式读入内存,其大小可能会有所不同,并且不受您的直接控制。
假设文件中的每一行都相当小,这已经非常节省内存了。
假设您的 "certain condition" 是一个简单的字符串匹配,进一步优化(针对网络和计算资源)的一种方法是使用 S3 Select:https://aws.amazon.com/s3/features/#s3-select
我在 AWS S3 中有一个非常大的文件(几 GB),我只需要文件中满足特定条件的少量行。我不想将整个文件加载到内存中,然后搜索并打印那几行——这样做的内存负载会太高。正确的方法是只加载内存中需要的那些行。
根据 AWS 文档to read from file:
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 逐行读取?还是介于两者之间?
取决于文件中行的大小。 readLine() 将继续构建字符串,以缓冲区大小的块为单位从流中获取数据,直到您遇到行终止符。所以使用的内存将是你的行长+缓冲区长度的顺序。
您链接的文档中已经给出了您问题的其中一个答案:
Your network connection remains open until you read all of the data or close the input stream.
A BufferedReader
不知道它读取的数据来自哪里,因为您正在将另一个 Reader
传递给它。 BufferedReader
创建一个特定大小的缓冲区(例如 4096 个字符),并在开始分发 read()
或 [=15 的调用数据之前通过从底层 Reader
读取来填充此缓冲区=].
你传递给 BufferedReader
的 Reader
是 - 顺便说一句 - 使用另一个缓冲区来完成从基于 byte
的流到 char
基reader。它的工作方式与 BufferedReader
相同,因此内部缓冲区通过读取传递的 InputStream
来填充,这是由您的 S3 客户端编辑的 InputStream
return。
如果您尝试从流中加载数据,此客户端中究竟发生了什么取决于实现。一种方法是保持打开一个网络连接,您可以根据需要从中读取,或者可以在读取一大块数据后关闭网络连接,并在您尝试获取下一个数据时打开一个新连接。
上面引用的文档似乎说我们这里有前一种情况,所以:不,readLine
的调用不会导致单个网络调用。
并回答您的其他问题:不,BufferedReader
、InputStreamReader
和很可能由 S3 客户端编辑的 InputStream
return 没有加载将整个文件存入内存。这将与首先使用流的整个目的相矛盾,S3 客户端可以简单地 return 一个 byte[][]
来代替(绕过每个 byte
数组 2^32 字节的限制)
编辑:最后一段有一个例外。如果整个千兆字节的大文档没有换行符,调用 readLine
实际上会导致将整个数据读入内存(并且很可能导致 OutOfMemoryError)。我在回答您的问题时假设了一个 "regular" 文本文档。
如果您基本上不是在搜索特定的 word/words,并且知道字节范围,您也可以在 S3 中使用范围 header。当您处理一个几 GB 大小的文件时,这应该特别有用。指定 Range 不仅有助于减少内存,而且速度更快,因为只读取文件的指定部分。
见Is there "S3 range read function" that allows to read assigned byte range from AWS-S3 file?
希望对您有所帮助。
Sreram
只对 AWS 基础设施进行一次 HTTP 调用,数据以小块的形式读入内存,其大小可能会有所不同,并且不受您的直接控制。
假设文件中的每一行都相当小,这已经非常节省内存了。
假设您的 "certain condition" 是一个简单的字符串匹配,进一步优化(针对网络和计算资源)的一种方法是使用 S3 Select:https://aws.amazon.com/s3/features/#s3-select