Java 逐行过滤输入流
我正在从AmazonS3检索大型gzip文件。我希望能够动态转换这些文件的每一行,并将输出上传到另一个S3存储桶 upload API以一个作为输入Java 逐行过滤输入流,java,Java,我正在从AmazonS3检索大型gzip文件。我希望能够动态转换这些文件的每一行,并将输出上传到另一个S3存储桶 upload API以一个作为输入 S3Object s3object = s3.fetch(bucket, key); InputStream is = new GZIPInputStream(s3object.getObjectContent()); // . . . ? s3.putObject(new PutObjectRequest(bucket, key, is,
S3Object s3object = s3.fetch(bucket, key);
InputStream is = new GZIPInputStream(s3object.getObjectContent());
// . . . ?
s3.putObject(new PutObjectRequest(bucket, key, is, metadata));
我相信最有效的方法是创建自己的自定义输入流,将原始输入流转换为另一个输入流。我不太熟悉这种方法,很想了解更多 基本思想如下
new BufferedReader(is).lines()
这不是非常有效,但应该完成这项工作
public class MyInputStream extends InputStream {
private final BufferedReader input;
private final Charset encoding = StandardCharsets.UTF_8;
private ByteArrayInputStream buffer;
public MyInputStream(InputStream is) throws IOException {
input = new BufferedReader(new InputStreamReader(is, this.encoding));
nextLine();
}
@Override
public int read() throws IOException {
if (buffer == null) {
return -1;
}
int ch = buffer.read();
if (ch == -1) {
if (!nextLine()) {
return -1;
}
return read();
}
return ch;
}
private boolean nextLine() throws IOException {
String line;
while ((line = input.readLine()) != null) {
line = filterLine(line);
if (line != null) {
line += '\n';
buffer = new ByteArrayInputStream(line.getBytes(encoding));
return true;
}
}
return false;
}
@Override
public void close() throws IOException {
input.close();
}
private String filterLine(String line) {
// Filter the line here ... return null to skip the line
// For example:
return line.replace("ABC", "XYZ");
}
}
nextLine()。然后read()
(由上载作业调用)逐个从缓冲区提取字节,并再次调用nextLine()
,以加载下一行
用作:
s3.putObject(new PutObjectRequest(bucket, key, new MyInputStream(is), metadata));
性能改进还可以实现int-read(byte[]b,int-off,int-len)
方法(如果cpu使用率很高),并在S3客户端内部不使用缓冲区(我不知道)的情况下使用BufferedInputStream
这不是非常有效,但应该完成这项工作
public class MyInputStream extends InputStream {
private final BufferedReader input;
private final Charset encoding = StandardCharsets.UTF_8;
private ByteArrayInputStream buffer;
public MyInputStream(InputStream is) throws IOException {
input = new BufferedReader(new InputStreamReader(is, this.encoding));
nextLine();
}
@Override
public int read() throws IOException {
if (buffer == null) {
return -1;
}
int ch = buffer.read();
if (ch == -1) {
if (!nextLine()) {
return -1;
}
return read();
}
return ch;
}
private boolean nextLine() throws IOException {
String line;
while ((line = input.readLine()) != null) {
line = filterLine(line);
if (line != null) {
line += '\n';
buffer = new ByteArrayInputStream(line.getBytes(encoding));
return true;
}
}
return false;
}
@Override
public void close() throws IOException {
input.close();
}
private String filterLine(String line) {
// Filter the line here ... return null to skip the line
// For example:
return line.replace("ABC", "XYZ");
}
}
nextLine()。然后read()
(由上载作业调用)逐个从缓冲区提取字节,并再次调用nextLine()
,以加载下一行
用作:
s3.putObject(new PutObjectRequest(bucket, key, new MyInputStream(is), metadata));
性能改进还可以实现int read(byte[]b,int off,int len)
方法(如果cpu使用率很高),并在S3客户端内部不使用缓冲区(我不知道)的情况下使用BufferedInputStream
。@gygabyte只有40个声誉,他/她不能发表评论BufferedReader
没有接受InputStream
的构造函数@gygabyte只有40个声誉,他/她不能发表评论BufferedReader
没有接受InputStream
的构造函数。感谢您的帮助。应该nextLine()代码>可以从read()调用代码>而不是构造函数?是否指定了内容长度?S3显示为内容长度。这意味着您需要将整个对象缓冲在某个位置或提取两次。在我的实现中,我扩展了FilterInputStream,而不是InputStream,后者还需要实现读取(字节、偏移量、长度)。请记住,这个例子总是添加一个尾随的新行,不管源代码是否有,但这通常是您想要的,但我将此设置为可选。谢谢您的帮助。应该nextLine()代码>可以从read()调用代码>而不是构造函数?是否指定了内容长度?S3显示为内容长度。这意味着您需要将整个对象缓冲在某个位置或提取两次。在我的实现中,我扩展了FilterInputStream,而不是InputStream,后者还需要实现读取(字节、偏移量、长度)。请记住,这个例子总是添加一个尾随的新行,不管源代码是否有一行,但这通常是您想要的,但我将其设置为可选。