我有以下方法:
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()
),它将用于一一读取数据 block 。因此,这个输入流必须缓冲读取的 block ,将其流回,当其缓冲区为空时,它应该读取下一个 block 。
这个想法是,仅当“客户端”从输入流中读取下一个字节时,我才从迭代器读取下一个元素。
或者可能还有另一种可能性来更改我的方法,使其返回 InputStream
而不是String
- 有什么想法吗?
最佳答案
如果您允许您的方法接受 java.io.Writer
,则可以避免整个 InputStream
实现。您无需将字符串附加到内存 StringBuilder
中,而是将它们附加到提供的 Writer 中。
public void exportAsCsv(CqlQuery query, Writer writer) {
Iterator<String> result = queryService.execute(.....);
for (String nextLine : result) {
writer.append(nextLine);
}
}
如果你真的想要一个输入流,你可以尝试这样的事情:
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);
}
}
};
}
我还没有实际测试过这种方法,所以请注意;不过,从概念上讲,我认为这就是您所追求的。
关于java - CSV 导出器的输入流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24207613/