我有以下方法:
public String exportAsCsv(CqlQuery query) {
Iterator<String> result = queryService.execute(.....);
StringBuilder buf = new StringBuilder();
for (String nextLine : result) {
buf.append(nextLine);
}
return buf.toString();
}
它执行一些返回Iterator<String>
的查询 - 它包含千兆字节的数据,因此将其附加到StringBuilder
并不是最好的想法......
我想更改我的方法,以便它返回InputStream
。
这可能是一种可能的实现(伪代码):
public InputStream exportAsCsv(CqlQuery query) {
final Iterator<String> result = queryService.execute(query,false);
return new MagicalInputStream(){
@Overwrite
byte[] readNext() {
if(!result.hasNext()) {
return null;
} else {
return result.next().getBytes();
}
}
}
}
我正在寻找InputStream
,我必须实现抽象方法(如byte[] readNext()
),它将用于逐个读取数据块。因此,此输入流必须缓冲读取块,将其流回,并且当其缓冲区为空时,它应读取下一个块。
我的想法是,当“客户端”从输入流中拉出下一个字节时,我只读取Iterator中的下一个元素。
或者可能有另一种可能性来更改我的方法,以便它返回InputStream
而不是String
- 任何想法?
答案 0 :(得分:2)
如果您允许方法接受InputStream
,则可以避免整个java.io.Writer
实施。您可以将它们附加到提供的Writer,而不是将字符串附加到内存中StringBuilder
。
public void exportAsCsv(CqlQuery query, Writer writer) {
Iterator<String> result = queryService.execute(.....);
for (String nextLine : result) {
writer.append(nextLine);
}
}
如果你真的想要一个InputStream,你可以尝试这样的事情:
public InputStream exportAsCsv(CqlQuery query) {
Iterator<String> result = queryService.execute(.....);
return new SequenceInputStream(asStreamEnum(result));
}
private Enumeration<InputStream> asStreamEnum(final Iterator<String> it) {
return new Enumeration<InputStream>() {
@Override
public boolean hasMoreElements() {
return it.hasNext();
}
@Override
public InputStream nextElement() {
try {
return new ByteArrayInputStream(it.next().getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
}
};
}
我还没有真正测试过这种方法,所以请注意;但从概念上讲,我认为这就是你所追求的目标。