sbh*_*tla 5 java inputstream bufferedinputstream amazon-s3 bufferedreader
我在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();
}
Run Code Online (Sandbox Code Playgroud)
这里我们使用BufferedReader.我不清楚这里发生了什么.
我们每次读取新行时是否对S3进行网络调用,并且只将当前行保留在缓冲区中?或者是整个文件加载到内存中,然后由BufferedReader逐行读取?或者介于两者之间?
您链接的文档中已经给出了您的问题的答案之一:
在您读取所有数据或关闭输入流之前,您的网络连接将保持打开状态.
A BufferedReader不知道它所读取的数据来自哪里,因为你将另一个数据传递Reader给它.甲BufferedReader创建特定大小(例如4096个字符)的缓冲液,并通过从底层填充读取该缓冲器Reader开始分发的呼叫数据之前read()或read(char[] buf).
顺便说一句,Reader你传递给BufferedReaderis - 使用另一个缓冲区来自己进行从byte基于流char的读取器到基于读取器的转换.它的工作原理相同的方式,用BufferedReader,因此内部缓冲区由从通过读取填充InputStream它是InputStream由您的S3-客户端返回.
如果您尝试从流中加载数据,那么此客户端中究竟发生了什么是依赖于实现的.一种方法是保持打开一个网络连接,您可以根据需要从中读取,或者在读取一大块数据后关闭网络连接,并在尝试获取下一个数据时打开一个新的网络连接.
上面引用的文档似乎说我们在这里遇到了前一种情况,所以:不,呼叫readLine不会导致单个网络呼叫.
并回答你的另一个问题:不,a BufferedReader,S3客户端返回的InputStreamReader,最有可能的InputStream是没有将整个文档加载到内存中.这与首先使用流的整个目的相矛盾,而S3客户端可以简单地返回一个byte[][](每个byte阵列大约2 ^ 32字节的限制)
编辑:最后一段有一个例外.如果整个千兆字节的大文档没有换行符,调用readLine实际上会导致将整个数据读入内存(最有可能是OutOfMemoryError).在回答您的问题时,我假设了一份"常规"文本文档.